├── .githooks └── pre-commit ├── .github ├── release.yml └── workflows │ └── test.yml ├── .gitignore ├── .prettierignore ├── README.md ├── e2e ├── .eslintrc.json ├── .gitignore ├── README.md ├── api │ └── graphql │ │ ├── api.graphqls │ │ └── query.graphql ├── generated │ └── typescript │ │ ├── fragment-masking.ts │ │ ├── gql.ts │ │ ├── graphql.ts │ │ ├── hooks.tsx │ │ └── index.ts ├── graphql-codegen.ts ├── next.config.mjs ├── package.json ├── playwright.config.ts ├── src │ └── app │ │ ├── ApolloWarapper.tsx │ │ ├── favicon.ico │ │ ├── globals.css │ │ ├── layout.tsx │ │ ├── page.module.css │ │ ├── page.play.ts │ │ └── page.tsx └── tsconfig.json ├── lerna.json ├── nx.json ├── package.json ├── packages └── @newmo │ ├── graphql-codegen-plugin-type-guards │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ │ ├── config.ts │ │ ├── convertName.ts │ │ └── graphql-codegen-plugin-type-guards.ts │ ├── test │ │ ├── api │ │ │ └── graphql │ │ │ │ ├── api.graphqls │ │ │ │ └── query.graphql │ │ ├── graphql-codegen.ts │ │ └── snapshots │ │ │ └── typescript │ │ │ ├── fragment-masking.ts │ │ │ ├── gql.ts │ │ │ ├── graphql.ts │ │ │ └── index.ts │ └── tsconfig.json │ └── graphql-codegen-plugin-typescript-react-apollo │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ ├── config.ts │ ├── convertName.ts │ └── graphql-codegen-plugin-typescript-react-apollo.ts │ ├── test │ ├── api │ │ └── graphql │ │ │ ├── api.graphqls │ │ │ └── query.graphql │ ├── graphql-codegen.ts │ └── snapshots │ │ └── typescript │ │ ├── fragment-masking.ts │ │ ├── gql.ts │ │ ├── graphql.ts │ │ ├── hooks.tsx │ │ └── index.ts │ └── tsconfig.json ├── pnpm-lock.yaml └── pnpm-workspace.yaml /.githooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | npx --no-install lint-staged 3 | -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | changelog: 2 | exclude: 3 | labels: 4 | - 'Type: Meta' 5 | - 'Type: Question' 6 | - 'Type: Release' 7 | 8 | categories: 9 | - title: Security Fixes 10 | labels: ['Type: Security'] 11 | - title: Breaking Changes 12 | labels: ['Type: Breaking Change'] 13 | - title: Features 14 | labels: ['Type: Feature'] 15 | - title: Bug Fixes 16 | labels: ['Type: Bug'] 17 | - title: Documentation 18 | labels: ['Type: Documentation'] 19 | - title: Refactoring 20 | labels: ['Type: Refactoring'] 21 | - title: Testing 22 | labels: ['Type: Testing'] 23 | - title: Maintenance 24 | labels: ['Type: Maintenance'] 25 | - title: CI 26 | labels: ['Type: CI'] 27 | - title: Dependency Updates 28 | labels: ['Type: Dependencies', "dependencies"] 29 | - title: Other Changes 30 | labels: ['*'] 31 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | on: [ push, pull_request ] 3 | permissions: 4 | contents: read 5 | jobs: 6 | test: 7 | name: "Test on Node.js ${{ matrix.node-version }}" 8 | runs-on: ubuntu-latest 9 | strategy: 10 | matrix: 11 | node-version: [ 18, 20 ] 12 | steps: 13 | - name: checkout 14 | uses: actions/checkout@v3 15 | - uses: pnpm/action-setup@v4.0.0 16 | - name: setup Node.js ${{ matrix.node-version }} 17 | uses: actions/setup-node@v3 18 | with: 19 | cache: "pnpm" 20 | node-version: ${{ matrix.node-version }} 21 | - name: Install 22 | run: pnpm install 23 | - name: Test 24 | run: pnpm test 25 | e2e: 26 | name: "E2E Tests" 27 | runs-on: ubuntu-latest 28 | steps: 29 | - name: checkout 30 | uses: actions/checkout@v3 31 | - uses: pnpm/action-setup@v4.0.0 32 | - name: setup Node.js 33 | uses: actions/setup-node@v3 34 | with: 35 | cache: "pnpm" 36 | node-version: 20 37 | - name: Install 38 | run: pnpm install 39 | - name: Playwright Install 40 | run: pnpm playwright install --with-deps 41 | working-directory: e2e/ 42 | - name: Build All 43 | run: pnpm run build 44 | - name: Playwright Test 45 | run: pnpm run e2e 46 | working-directory: e2e/ 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .nx 2 | lib/ 3 | .next/ 4 | ### Generated by gibo (https://github.com/simonwhitaker/gibo) 5 | ### https://raw.github.com/github/gitignore/4488915eec0b3a45b5c63ead28f286819c0917de/Node.gitignore 6 | 7 | # Logs 8 | logs 9 | *.log 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | lerna-debug.log* 14 | .pnpm-debug.log* 15 | 16 | # Diagnostic reports (https://nodejs.org/api/report.html) 17 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 18 | 19 | # Runtime data 20 | pids 21 | *.pid 22 | *.seed 23 | *.pid.lock 24 | 25 | # Directory for instrumented libs generated by jscoverage/JSCover 26 | lib-cov 27 | 28 | # Coverage directory used by tools like istanbul 29 | coverage 30 | *.lcov 31 | 32 | # nyc test coverage 33 | .nyc_output 34 | 35 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 36 | .grunt 37 | 38 | # Bower dependency directory (https://bower.io/) 39 | bower_components 40 | 41 | # node-waf configuration 42 | .lock-wscript 43 | 44 | # Compiled binary addons (https://nodejs.org/api/addons.html) 45 | build/Release 46 | 47 | # Dependency directories 48 | node_modules/ 49 | jspm_packages/ 50 | 51 | # Snowpack dependency directory (https://snowpack.dev/) 52 | web_modules/ 53 | 54 | # TypeScript cache 55 | *.tsbuildinfo 56 | 57 | # Optional npm cache directory 58 | .npm 59 | 60 | # Optional eslint cache 61 | .eslintcache 62 | 63 | # Optional stylelint cache 64 | .stylelintcache 65 | 66 | # Microbundle cache 67 | .rpt2_cache/ 68 | .rts2_cache_cjs/ 69 | .rts2_cache_es/ 70 | .rts2_cache_umd/ 71 | 72 | # Optional REPL history 73 | .node_repl_history 74 | 75 | # Output of 'npm pack' 76 | *.tgz 77 | 78 | # Yarn Integrity file 79 | .yarn-integrity 80 | 81 | # dotenv environment variable files 82 | .env 83 | .env.development.local 84 | .env.test.local 85 | .env.production.local 86 | .env.local 87 | 88 | # parcel-bundler cache (https://parceljs.org/) 89 | .cache 90 | .parcel-cache 91 | 92 | # Next.js build output 93 | .next 94 | out 95 | 96 | # Nuxt.js build / generate output 97 | .nuxt 98 | dist 99 | 100 | # Gatsby files 101 | .cache/ 102 | # Comment in the public line in if your project uses Gatsby and not Next.js 103 | # https://nextjs.org/blog/next-9-1#public-directory-support 104 | # public 105 | 106 | # vuepress build output 107 | .vuepress/dist 108 | 109 | # vuepress v2.x temp and cache directory 110 | .temp 111 | .cache 112 | 113 | # Docusaurus cache and generated files 114 | .docusaurus 115 | 116 | # Serverless directories 117 | .serverless/ 118 | 119 | # FuseBox cache 120 | .fusebox/ 121 | 122 | # DynamoDB Local files 123 | .dynamodb/ 124 | 125 | # TernJS port file 126 | .tern-port 127 | 128 | # Stores VSCode versions used for testing VSCode extensions 129 | .vscode-test 130 | 131 | # yarn v2 132 | .yarn/cache 133 | .yarn/unplugged 134 | .yarn/build-state.yml 135 | .yarn/install-state.gz 136 | .pnp.* 137 | ### Generated by gibo (https://github.com/simonwhitaker/gibo) 138 | ### https://raw.github.com/github/gitignore/4488915eec0b3a45b5c63ead28f286819c0917de/Global/JetBrains.gitignore 139 | 140 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 141 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 142 | 143 | # User-specific stuff 144 | .idea/**/workspace.xml 145 | .idea/**/tasks.xml 146 | .idea/**/usage.statistics.xml 147 | .idea/**/dictionaries 148 | .idea/**/shelf 149 | 150 | # AWS User-specific 151 | .idea/**/aws.xml 152 | 153 | # Generated files 154 | .idea/**/contentModel.xml 155 | 156 | # Sensitive or high-churn files 157 | .idea/**/dataSources/ 158 | .idea/**/dataSources.ids 159 | .idea/**/dataSources.local.xml 160 | .idea/**/sqlDataSources.xml 161 | .idea/**/dynamic.xml 162 | .idea/**/uiDesigner.xml 163 | .idea/**/dbnavigator.xml 164 | 165 | # Gradle 166 | .idea/**/gradle.xml 167 | .idea/**/libraries 168 | 169 | # Gradle and Maven with auto-import 170 | # When using Gradle or Maven with auto-import, you should exclude module files, 171 | # since they will be recreated, and may cause churn. Uncomment if using 172 | # auto-import. 173 | # .idea/artifacts 174 | # .idea/compiler.xml 175 | # .idea/jarRepositories.xml 176 | # .idea/modules.xml 177 | # .idea/*.iml 178 | # .idea/modules 179 | # *.iml 180 | # *.ipr 181 | 182 | # CMake 183 | cmake-build-*/ 184 | 185 | # Mongo Explorer plugin 186 | .idea/**/mongoSettings.xml 187 | 188 | # File-based project format 189 | *.iws 190 | 191 | # IntelliJ 192 | out/ 193 | 194 | # mpeltonen/sbt-idea plugin 195 | .idea_modules/ 196 | 197 | # JIRA plugin 198 | atlassian-ide-plugin.xml 199 | 200 | # Cursive Clojure plugin 201 | .idea/replstate.xml 202 | 203 | # SonarLint plugin 204 | .idea/sonarlint/ 205 | 206 | # Crashlytics plugin (for Android Studio and IntelliJ) 207 | com_crashlytics_export_strings.xml 208 | crashlytics.properties 209 | crashlytics-build.properties 210 | fabric.properties 211 | 212 | # Editor-based Rest Client 213 | .idea/httpRequests 214 | 215 | # Android studio 3.1+ serialized cache file 216 | .idea/caches/build_file_checksums.ser 217 | ### Generated by gibo (https://github.com/simonwhitaker/gibo) 218 | ### https://raw.github.com/github/gitignore/4488915eec0b3a45b5c63ead28f286819c0917de/Global/VisualStudioCode.gitignore 219 | 220 | .vscode/* 221 | !.vscode/settings.json 222 | !.vscode/tasks.json 223 | !.vscode/launch.json 224 | !.vscode/extensions.json 225 | !.vscode/*.code-snippets 226 | 227 | # Local History for Visual Studio Code 228 | .history/ 229 | 230 | # Built Visual Studio Code Extensions 231 | *.vsix 232 | # Build files 233 | /lib 234 | /module 235 | 236 | .nx/cache 237 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | generated/ 2 | snapshots/ 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GraphQL Code Generator Plugins 2 | 3 | This monorepo contains GraphQL Code Generator plugins. 4 | 5 | ## Packages 6 | 7 | - [@newmo/graphql-codegen-plugin-typescript-react-apollo](./packages/@newmo/graphql-codegen-plugin-typescript-react-apollo) 8 | - TypeScript React Apollo plugin for GraphQL Code Generator 9 | - [@newmo/graphql-codegen-plugin-type-guards](./packages/@newmo/graphql-codegen-plugin-type-guards) 10 | - TypeScript type guards plugin for GraphQL Code Generator 11 | 12 | ## Development 13 | 14 | This repository uses pnpm as package manager. 15 | 16 | ### Install dependencies 17 | 18 | ```sh 19 | pnpm install 20 | ``` 21 | 22 | ### Build 23 | 24 | ```sh 25 | pnpm run build 26 | ``` 27 | 28 | ### Test 29 | 30 | ```sh 31 | pnpm run test 32 | ``` 33 | 34 | ## License 35 | 36 | MIT 37 | -------------------------------------------------------------------------------- /e2e/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /e2e/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | /test-results/ 38 | /playwright-report/ 39 | /blob-report/ 40 | /playwright/.cache/ 41 | -------------------------------------------------------------------------------- /e2e/README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 20 | 21 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 22 | 23 | ## Learn More 24 | 25 | To learn more about Next.js, take a look at the following resources: 26 | 27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 29 | 30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 31 | 32 | ## Deploy on Vercel 33 | 34 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 35 | 36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 37 | -------------------------------------------------------------------------------- /e2e/api/graphql/api.graphqls: -------------------------------------------------------------------------------- 1 | """ 2 | @exampleString directive specifies an example value for a String field. 3 | This example value is used in the fake data. 4 | 5 | Note: This is for @newmo/graphql-fake-server 6 | """ 7 | directive @exampleString( 8 | """ 9 | The value of the String field. 10 | @exampleString(value: "example") 11 | """ 12 | value: String! 13 | ) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION 14 | 15 | 16 | type Query { 17 | """ 18 | Get the list of destination candidates. 19 | """ 20 | destinationCandidates(text: String!): [Destination!]! 21 | 22 | """ 23 | Get the list of ride histories. 24 | """ 25 | rideHistories: [RideHistory!]! 26 | } 27 | 28 | type RideHistory { 29 | "ID of the ride history." 30 | id: ID! 31 | 32 | "Destination of the ride history." 33 | destination: Destination! 34 | } 35 | 36 | enum DestinationType { 37 | "Airport" 38 | AIRPORT 39 | 40 | "Station" 41 | STATION 42 | 43 | "City" 44 | CITY 45 | } 46 | 47 | type Destination { 48 | "ID of the destination." 49 | id: ID! 50 | 51 | "Name of the destination." 52 | name: String! @exampleString(value: "Osaka") 53 | 54 | "Type of the destination." 55 | type: DestinationType! 56 | } 57 | """ 58 | Error interface 59 | """ 60 | interface Error { 61 | "Error message." 62 | message: String! 63 | } 64 | type TextError implements Error { 65 | "Error message." 66 | message: String! 67 | 68 | "Localized error message." 69 | localizedMessage: String! 70 | } 71 | """ 72 | Specified Error type for createRideHistory mutation. 73 | """ 74 | type CreateRideHistoryErrorDetails implements Error{ 75 | code: Int! 76 | message: String! 77 | localizedMessage: String! 78 | } 79 | union ErrorUnion = TextError | CreateRideHistoryErrorDetails 80 | 81 | input RideHistoryInput { 82 | "Name of the destination." 83 | name: String! @exampleString(value: "Tokyo") 84 | } 85 | type RideHistoryOutput { 86 | "ID of the ride history." 87 | id: ID! 88 | "Name of the destination." 89 | name: String! @exampleString(value: "Tokyo") 90 | 91 | "Error." 92 | errors: [ErrorUnion!]! 93 | } 94 | """ 95 | namingConvention test 96 | - URL 97 | - Create* 98 | """ 99 | type FooURLResource { 100 | "Foo URL" 101 | URL: String! 102 | } 103 | input FooURLInput { 104 | "Foo URL" 105 | URL: String! 106 | } 107 | type FooURLPayload { 108 | "Foo URL" 109 | URL: String! 110 | "Errors" 111 | errors: [CreateFooURLError!]! 112 | } 113 | union CreateFooURLError = CreateFooURLErrorDetail 114 | type CreateFooURLErrorDetail implements Error { 115 | code: CreateFooURLErrorCode! 116 | message: String! 117 | localizedMessage: String! 118 | } 119 | enum CreateFooURLErrorCode { 120 | FAILED_TO_CREATE_FOO_URL 121 | } 122 | 123 | type Mutation { 124 | """ 125 | Create Ride History 126 | """ 127 | createRideHistory(input: RideHistoryInput!): RideHistoryOutput! 128 | 129 | """ 130 | Create Foo URL 131 | """ 132 | createFooURL(input: FooURLInput!): FooURLPayload! 133 | } 134 | -------------------------------------------------------------------------------- /e2e/api/graphql/query.graphql: -------------------------------------------------------------------------------- 1 | query ListDestinationCandidates($text: String!) { 2 | destinationCandidates(text: $text) { 3 | id 4 | name 5 | } 6 | } 7 | 8 | query ListRideHistories { 9 | rideHistories { 10 | id 11 | destination { 12 | id 13 | name 14 | } 15 | } 16 | } 17 | 18 | mutation CreateRideHistory($desinationName: String!) { 19 | createRideHistory(input: { name: $desinationName }){ 20 | id 21 | name 22 | errors { 23 | ... on TextError { 24 | message 25 | localizedMessage 26 | } 27 | ... on Error { 28 | message 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /e2e/generated/typescript/fragment-masking.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import type { ResultOf, DocumentTypeDecoration, TypedDocumentNode } from '@graphql-typed-document-node/core'; 3 | import type { FragmentDefinitionNode } from 'graphql'; 4 | import type { Incremental } from './graphql'; 5 | 6 | 7 | export type FragmentType> = TDocumentType extends DocumentTypeDecoration< 8 | infer TType, 9 | any 10 | > 11 | ? [TType] extends [{ ' $fragmentName'?: infer TKey }] 12 | ? TKey extends string 13 | ? { ' $fragmentRefs'?: { [key in TKey]: TType } } 14 | : never 15 | : never 16 | : never; 17 | 18 | // return non-nullable if `fragmentType` is non-nullable 19 | export function getFragmentData( 20 | _documentNode: DocumentTypeDecoration, 21 | fragmentType: FragmentType> 22 | ): TType; 23 | // return nullable if `fragmentType` is nullable 24 | export function getFragmentData( 25 | _documentNode: DocumentTypeDecoration, 26 | fragmentType: FragmentType> | null | undefined 27 | ): TType | null | undefined; 28 | // return array of non-nullable if `fragmentType` is array of non-nullable 29 | export function getFragmentData( 30 | _documentNode: DocumentTypeDecoration, 31 | fragmentType: ReadonlyArray>> 32 | ): ReadonlyArray; 33 | // return array of nullable if `fragmentType` is array of nullable 34 | export function getFragmentData( 35 | _documentNode: DocumentTypeDecoration, 36 | fragmentType: ReadonlyArray>> | null | undefined 37 | ): ReadonlyArray | null | undefined; 38 | export function getFragmentData( 39 | _documentNode: DocumentTypeDecoration, 40 | fragmentType: FragmentType> | ReadonlyArray>> | null | undefined 41 | ): TType | ReadonlyArray | null | undefined { 42 | return fragmentType as any; 43 | } 44 | 45 | 46 | export function makeFragmentData< 47 | F extends DocumentTypeDecoration, 48 | FT extends ResultOf 49 | >(data: FT, _fragment: F): FragmentType { 50 | return data as FragmentType; 51 | } 52 | export function isFragmentReady( 53 | queryNode: DocumentTypeDecoration, 54 | fragmentNode: TypedDocumentNode, 55 | data: FragmentType, any>> | null | undefined 56 | ): data is FragmentType { 57 | const deferredFields = (queryNode as { __meta__?: { deferredFields: Record } }).__meta__ 58 | ?.deferredFields; 59 | 60 | if (!deferredFields) return true; 61 | 62 | const fragDef = fragmentNode.definitions[0] as FragmentDefinitionNode | undefined; 63 | const fragName = fragDef?.name?.value; 64 | 65 | const fields = (fragName && deferredFields[fragName]) || []; 66 | return fields.length > 0 && fields.every(field => data && field in data); 67 | } 68 | -------------------------------------------------------------------------------- /e2e/generated/typescript/gql.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import * as types from './graphql'; 3 | import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; 4 | 5 | /** 6 | * Map of all GraphQL operations in the project. 7 | * 8 | * This map has several performance disadvantages: 9 | * 1. It is not tree-shakeable, so it will include all operations in the project. 10 | * 2. It is not minifiable, so the string of a GraphQL query will be multiple times inside the bundle. 11 | * 3. It does not support dead code elimination, so it will add unused operations. 12 | * 13 | * Therefore it is highly recommended to use the babel or swc plugin for production. 14 | */ 15 | const documents = { 16 | "query ListDestinationCandidates($text: String!) {\n destinationCandidates(text: $text) {\n id\n name\n }\n}\n\nquery ListRideHistories {\n rideHistories {\n id\n destination {\n id\n name\n }\n }\n}\n\nmutation CreateRideHistory($desinationName: String!) {\n createRideHistory(input: {name: $desinationName}) {\n id\n name\n errors {\n ... on TextError {\n message\n localizedMessage\n }\n ... on Error {\n message\n }\n }\n }\n}": types.ListDestinationCandidatesDocument, 17 | }; 18 | 19 | /** 20 | * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. 21 | * 22 | * 23 | * @example 24 | * ```ts 25 | * const query = graphql(`query GetUser($id: ID!) { user(id: $id) { name } }`); 26 | * ``` 27 | * 28 | * The query argument is unknown! 29 | * Please regenerate the types. 30 | */ 31 | export function graphql(source: string): unknown; 32 | 33 | /** 34 | * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. 35 | */ 36 | export function graphql(source: "query ListDestinationCandidates($text: String!) {\n destinationCandidates(text: $text) {\n id\n name\n }\n}\n\nquery ListRideHistories {\n rideHistories {\n id\n destination {\n id\n name\n }\n }\n}\n\nmutation CreateRideHistory($desinationName: String!) {\n createRideHistory(input: {name: $desinationName}) {\n id\n name\n errors {\n ... on TextError {\n message\n localizedMessage\n }\n ... on Error {\n message\n }\n }\n }\n}"): (typeof documents)["query ListDestinationCandidates($text: String!) {\n destinationCandidates(text: $text) {\n id\n name\n }\n}\n\nquery ListRideHistories {\n rideHistories {\n id\n destination {\n id\n name\n }\n }\n}\n\nmutation CreateRideHistory($desinationName: String!) {\n createRideHistory(input: {name: $desinationName}) {\n id\n name\n errors {\n ... on TextError {\n message\n localizedMessage\n }\n ... on Error {\n message\n }\n }\n }\n}"]; 37 | 38 | export function graphql(source: string) { 39 | return (documents as any)[source] ?? {}; 40 | } 41 | 42 | export type DocumentType> = TDocumentNode extends DocumentNode< infer TType, any> ? TType : never; -------------------------------------------------------------------------------- /e2e/generated/typescript/graphql.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; 3 | export type Maybe = T | null; 4 | export type InputMaybe = Maybe; 5 | export type Exact = { [K in keyof T]: T[K] }; 6 | export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; 7 | export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; 8 | export type MakeEmpty = { [_ in K]?: never }; 9 | export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; 10 | /** All built-in and custom scalars, mapped to their actual values */ 11 | export type Scalars = { 12 | ID: { input: string; output: string; } 13 | String: { input: string; output: string; } 14 | Boolean: { input: boolean; output: boolean; } 15 | Int: { input: number; output: number; } 16 | Float: { input: number; output: number; } 17 | }; 18 | 19 | export type CreateFooUrlError = CreateFooUrlErrorDetail; 20 | 21 | export enum CreateFooUrlErrorCode { 22 | FailedToCreateFooUrl = 'FAILED_TO_CREATE_FOO_URL' 23 | } 24 | 25 | export type CreateFooUrlErrorDetail = Error & { 26 | __typename: 'CreateFooURLErrorDetail'; 27 | code: CreateFooUrlErrorCode; 28 | localizedMessage: Scalars['String']['output']; 29 | message: Scalars['String']['output']; 30 | }; 31 | 32 | /** Specified Error type for createRideHistory mutation. */ 33 | export type CreateRideHistoryErrorDetails = Error & { 34 | __typename: 'CreateRideHistoryErrorDetails'; 35 | code: Scalars['Int']['output']; 36 | localizedMessage: Scalars['String']['output']; 37 | message: Scalars['String']['output']; 38 | }; 39 | 40 | export type Destination = { 41 | __typename: 'Destination'; 42 | /** ID of the destination. */ 43 | id: Scalars['ID']['output']; 44 | /** Name of the destination. */ 45 | name: Scalars['String']['output']; 46 | /** Type of the destination. */ 47 | type: DestinationType; 48 | }; 49 | 50 | export enum DestinationType { 51 | /** Airport */ 52 | Airport = 'AIRPORT', 53 | /** City */ 54 | City = 'CITY', 55 | /** Station */ 56 | Station = 'STATION' 57 | } 58 | 59 | /** Error interface */ 60 | export type Error = { 61 | /** Error message. */ 62 | message: Scalars['String']['output']; 63 | }; 64 | 65 | export type ErrorUnion = CreateRideHistoryErrorDetails | TextError; 66 | 67 | export type FooUrlInput = { 68 | /** Foo URL */ 69 | URL: Scalars['String']['input']; 70 | }; 71 | 72 | export type FooUrlPayload = { 73 | __typename: 'FooURLPayload'; 74 | /** Foo URL */ 75 | URL: Scalars['String']['output']; 76 | /** Errors */ 77 | errors: Array; 78 | }; 79 | 80 | /** 81 | * namingConvention test 82 | * - URL 83 | * - Create* 84 | */ 85 | export type FooUrlResource = { 86 | __typename: 'FooURLResource'; 87 | /** Foo URL */ 88 | URL: Scalars['String']['output']; 89 | }; 90 | 91 | export type Mutation = { 92 | __typename: 'Mutation'; 93 | /** Create Foo URL */ 94 | createFooURL: FooUrlPayload; 95 | /** Create Ride History */ 96 | createRideHistory: RideHistoryOutput; 97 | }; 98 | 99 | 100 | export type MutationCreateFooUrlArgs = { 101 | input: FooUrlInput; 102 | }; 103 | 104 | 105 | export type MutationCreateRideHistoryArgs = { 106 | input: RideHistoryInput; 107 | }; 108 | 109 | export type Query = { 110 | __typename: 'Query'; 111 | /** Get the list of destination candidates. */ 112 | destinationCandidates: Array; 113 | /** Get the list of ride histories. */ 114 | rideHistories: Array; 115 | }; 116 | 117 | 118 | export type QueryDestinationCandidatesArgs = { 119 | text: Scalars['String']['input']; 120 | }; 121 | 122 | export type RideHistory = { 123 | __typename: 'RideHistory'; 124 | /** Destination of the ride history. */ 125 | destination: Destination; 126 | /** ID of the ride history. */ 127 | id: Scalars['ID']['output']; 128 | }; 129 | 130 | export type RideHistoryInput = { 131 | /** Name of the destination. */ 132 | name: Scalars['String']['input']; 133 | }; 134 | 135 | export type RideHistoryOutput = { 136 | __typename: 'RideHistoryOutput'; 137 | /** Error. */ 138 | errors: Array; 139 | /** ID of the ride history. */ 140 | id: Scalars['ID']['output']; 141 | /** Name of the destination. */ 142 | name: Scalars['String']['output']; 143 | }; 144 | 145 | export type TextError = Error & { 146 | __typename: 'TextError'; 147 | /** Localized error message. */ 148 | localizedMessage: Scalars['String']['output']; 149 | /** Error message. */ 150 | message: Scalars['String']['output']; 151 | }; 152 | 153 | export type ListDestinationCandidatesQueryVariables = Exact<{ 154 | text: Scalars['String']['input']; 155 | }>; 156 | 157 | 158 | export type ListDestinationCandidatesQuery = { __typename: 'Query', destinationCandidates: Array<{ __typename: 'Destination', id: string, name: string }> }; 159 | 160 | export type ListRideHistoriesQueryVariables = Exact<{ [key: string]: never; }>; 161 | 162 | 163 | export type ListRideHistoriesQuery = { __typename: 'Query', rideHistories: Array<{ __typename: 'RideHistory', id: string, destination: { __typename: 'Destination', id: string, name: string } }> }; 164 | 165 | export type CreateRideHistoryMutationVariables = Exact<{ 166 | desinationName: Scalars['String']['input']; 167 | }>; 168 | 169 | 170 | export type CreateRideHistoryMutation = { __typename: 'Mutation', createRideHistory: { __typename: 'RideHistoryOutput', id: string, name: string, errors: Array<{ __typename: 'CreateRideHistoryErrorDetails', message: string } | { __typename: 'TextError', message: string, localizedMessage: string }> } }; 171 | 172 | 173 | export const ListDestinationCandidatesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ListDestinationCandidates"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"text"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"destinationCandidates"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"text"},"value":{"kind":"Variable","name":{"kind":"Name","value":"text"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode; 174 | export const ListRideHistoriesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ListRideHistories"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"rideHistories"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"destination"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]} as unknown as DocumentNode; 175 | export const CreateRideHistoryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateRideHistory"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"desinationName"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createRideHistory"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"desinationName"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"TextError"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"localizedMessage"}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Error"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]}}]} as unknown as DocumentNode; 176 | export const isCreateFooUrlError = (field: { __typename?: string; }): field is CreateFooUrlError => { 177 | if(field.__typename === undefined) return false; 178 | return ["CreateFooUrlErrorDetail"].includes(field.__typename); 179 | }; 180 | export const isCreateFooUrlErrorDetail = (field: { __typename?: string; }): field is CreateFooUrlErrorDetail => field.__typename === 'CreateFooUrlErrorDetail'; 181 | export const isCreateRideHistoryErrorDetails = (field: { __typename?: string; }): field is CreateRideHistoryErrorDetails => field.__typename === 'CreateRideHistoryErrorDetails'; 182 | export const isDestination = (field: { __typename?: string; }): field is Destination => field.__typename === 'Destination'; 183 | export const isErrorUnion = (field: { __typename?: string; }): field is ErrorUnion => { 184 | if(field.__typename === undefined) return false; 185 | return ["CreateRideHistoryErrorDetails","TextError"].includes(field.__typename); 186 | }; 187 | export const isFooUrlPayload = (field: { __typename?: string; }): field is FooUrlPayload => field.__typename === 'FooUrlPayload'; 188 | export const isFooUrlResource = (field: { __typename?: string; }): field is FooUrlResource => field.__typename === 'FooUrlResource'; 189 | export const isMutation = (field: { __typename?: string; }): field is Mutation => field.__typename === 'Mutation'; 190 | export const isQuery = (field: { __typename?: string; }): field is Query => field.__typename === 'Query'; 191 | export const isRideHistory = (field: { __typename?: string; }): field is RideHistory => field.__typename === 'RideHistory'; 192 | export const isRideHistoryOutput = (field: { __typename?: string; }): field is RideHistoryOutput => field.__typename === 'RideHistoryOutput'; 193 | export const isTextError = (field: { __typename?: string; }): field is TextError => field.__typename === 'TextError'; -------------------------------------------------------------------------------- /e2e/generated/typescript/hooks.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // This file was generated by a @newmo/graphql-codegen-plugin-typescript-react-apollo 3 | import * as Apollo from '@apollo/client'; 4 | import { ListDestinationCandidatesDocument } from './graphql'; 5 | import type { ListDestinationCandidatesQuery, ListDestinationCandidatesQueryVariables } from './graphql'; 6 | import { ListRideHistoriesDocument } from './graphql'; 7 | import type { ListRideHistoriesQuery, ListRideHistoriesQueryVariables } from './graphql'; 8 | import { CreateRideHistoryDocument } from './graphql'; 9 | import type { CreateRideHistoryMutation, CreateRideHistoryMutationVariables } from './graphql'; 10 | export function useListDestinationCandidatesSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions): Apollo.UseSuspenseQueryResult { 11 | const options = { ...baseOptions }; 12 | return Apollo.useSuspenseQuery(ListDestinationCandidatesDocument, options); 13 | } 14 | export function useListRideHistoriesSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions): Apollo.UseSuspenseQueryResult { 15 | const options = { ...baseOptions }; 16 | return Apollo.useSuspenseQuery(ListRideHistoriesDocument, options); 17 | } 18 | export function useCreateRideHistorySuspenseMutation(baseOptions?: Apollo.MutationHookOptions): Apollo.MutationTuple { 19 | const options = { ...baseOptions }; 20 | return Apollo.useMutation(CreateRideHistoryDocument, options); 21 | } 22 | -------------------------------------------------------------------------------- /e2e/generated/typescript/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./fragment-masking"; 2 | export * from "./gql"; -------------------------------------------------------------------------------- /e2e/graphql-codegen.ts: -------------------------------------------------------------------------------- 1 | import type { CodegenConfig } from "@graphql-codegen/cli"; 2 | 3 | const config: CodegenConfig = { 4 | overwrite: true, 5 | schema: "./api/graphql/api.graphqls", 6 | documents: "./api/graphql/query.graphql", 7 | generates: { 8 | "./generated/typescript/": { 9 | preset: "client", 10 | config: { 11 | nonOptionalTypename: true, 12 | useTypeImports: true 13 | }, 14 | presetConfig: { 15 | fragmentMasking: { unmaskFunctionName: "getFragmentData" } 16 | }, 17 | plugins: ["@newmo/graphql-codegen-plugin-type-guards"] 18 | }, 19 | "./generated/typescript/hooks.tsx": { 20 | plugins: ["@newmo/graphql-codegen-plugin-typescript-react-apollo"], 21 | config: { 22 | typesFile: "./graphql" // required 23 | } 24 | } 25 | } 26 | }; 27 | 28 | export default config; 29 | -------------------------------------------------------------------------------- /e2e/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | "output": "export", 4 | }; 5 | 6 | export default nextConfig; 7 | -------------------------------------------------------------------------------- /e2e/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "@example/e2e", 4 | "version": "1.2.2", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "pnpm run /^dev:/", 8 | "dev:next": "next dev", 9 | "dev:api": "graphql-fake-server --schema ./api/graphql/api.graphqls", 10 | "build": "next build", 11 | "start": "next start", 12 | "lint": "next lint", 13 | "e2e": "playwright test", 14 | "e2e:ui": "playwright test --ui", 15 | "codegen": "graphql-codegen --config ./graphql-codegen.ts" 16 | }, 17 | "dependencies": { 18 | "@apollo/client": "^3.10.4", 19 | "@graphql-typed-document-node/core": "^3.2.0", 20 | "graphql": "^16.8.1", 21 | "next": "15.0.0-rc.0", 22 | "react": "19.0.0-rc-935180c7e0-20240524", 23 | "react-dom": "19.0.0-rc-935180c7e0-20240524", 24 | "react-error-boundary": "^4.0.13" 25 | }, 26 | "devDependencies": { 27 | "@graphql-codegen/cli": "5.0.0", 28 | "@graphql-codegen/client-preset": "^4.2.4", 29 | "@newmo/graphql-codegen-plugin-type-guards": "workspace:*", 30 | "@newmo/graphql-codegen-plugin-typescript-react-apollo": "workspace:*", 31 | "@newmo/graphql-fake-server": "^0.9.7", 32 | "@playwright/test": "^1.44.1", 33 | "@types/node": "^20", 34 | "@types/react": "npm:types-react@rc", 35 | "@types/react-dom": "npm:types-react-dom@rc", 36 | "eslint": "^8", 37 | "eslint-config-next": "14.2.1", 38 | "typescript": "^5" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /e2e/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, devices } from "@playwright/test"; 2 | 3 | /** 4 | * Read environment variables from file. 5 | * https://github.com/motdotla/dotenv 6 | */ 7 | // require('dotenv').config(); 8 | 9 | /** 10 | * See https://playwright.dev/docs/test-configuration. 11 | */ 12 | export default defineConfig({ 13 | testMatch: "**/*.play.ts", 14 | /* Run tests in files in parallel */ 15 | fullyParallel: true, 16 | /* Fail the build on CI if you accidentally left test.only in the source code. */ 17 | forbidOnly: !!process.env["CI"], 18 | /* Retry on CI only */ 19 | retries: process.env["CI"] ? 2 : 0, 20 | /* Opt out of parallel tests on CI. */ 21 | ...(process.env["CI"] ? { workers: 1 } : {}), 22 | /* Reporter to use. See https://playwright.dev/docs/test-reporters */ 23 | reporter: process.env["CI"] 24 | ? [ 25 | // githubAction(), 26 | ] 27 | : "list", 28 | /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ 29 | use: { 30 | /* Base URL to use in actions like `await page.goto('/')`. */ 31 | // baseURL: 'http://127.0.0.1:3000', 32 | 33 | /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ 34 | trace: "on-first-retry" 35 | }, 36 | 37 | /* Configure projects for major browsers */ 38 | projects: [ 39 | { 40 | name: "chromium", 41 | use: { ...devices["Desktop Chrome"] } 42 | } 43 | // 44 | // { 45 | // name: 'firefox', 46 | // use: { ...devices['Desktop Firefox'] }, 47 | // }, 48 | // 49 | // { 50 | // name: 'webkit', 51 | // use: { ...devices['Desktop Safari'] }, 52 | // }, 53 | 54 | /* Test against mobile viewports. */ 55 | // { 56 | // name: 'Mobile Chrome', 57 | // use: { ...devices['Pixel 5'] }, 58 | // }, 59 | // { 60 | // name: 'Mobile Safari', 61 | // use: { ...devices['iPhone 12'] }, 62 | // }, 63 | 64 | /* Test against branded browsers. */ 65 | // { 66 | // name: 'Microsoft Edge', 67 | // use: { ...devices['Desktop Edge'], channel: 'msedge' }, 68 | // }, 69 | // { 70 | // name: 'Google Chrome', 71 | // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, 72 | // }, 73 | ], 74 | /* Run your local dev server before starting the tests */ 75 | webServer: [ 76 | { 77 | command: "npm run dev:next", 78 | url: "http://127.0.0.1:3000", 79 | reuseExistingServer: !process.env["CI"] 80 | }, 81 | { 82 | command: "npm run dev:api", 83 | url: "http://127.0.0.1:4000", 84 | reuseExistingServer: !process.env["CI"] 85 | } 86 | ] 87 | }); 88 | -------------------------------------------------------------------------------- /e2e/src/app/ApolloWarapper.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { ApolloProvider } from "@apollo/client"; 3 | import { ApolloClient, InMemoryCache } from "@apollo/client"; 4 | 5 | export const client = new ApolloClient({ 6 | cache: new InMemoryCache(), 7 | uri: "http://localhost:4000/", 8 | ssrMode: false 9 | }); 10 | 11 | export const ApolloWrapper = ({ children }: { children: React.ReactNode }) => { 12 | return {children}; 13 | }; 14 | -------------------------------------------------------------------------------- /e2e/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/newmo-oss/graphql-codegen-plugins/40d5dfb5f9f2db5e772adc0ecc50ef1dc4f2e6ba/e2e/src/app/favicon.ico -------------------------------------------------------------------------------- /e2e/src/app/globals.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --max-width: 1100px; 3 | --border-radius: 12px; 4 | --font-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono", "Oxygen Mono", 5 | "Ubuntu Monospace", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", monospace; 6 | 7 | --foreground-rgb: 0, 0, 0; 8 | --background-start-rgb: 214, 219, 220; 9 | --background-end-rgb: 255, 255, 255; 10 | 11 | --primary-glow: conic-gradient( 12 | from 180deg at 50% 50%, 13 | #16abff33 0deg, 14 | #0885ff33 55deg, 15 | #54d6ff33 120deg, 16 | #0071ff33 160deg, 17 | transparent 360deg 18 | ); 19 | --secondary-glow: radial-gradient(rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)); 20 | 21 | --tile-start-rgb: 239, 245, 249; 22 | --tile-end-rgb: 228, 232, 233; 23 | --tile-border: conic-gradient(#00000080, #00000040, #00000030, #00000020, #00000010, #00000010, #00000080); 24 | 25 | --callout-rgb: 238, 240, 241; 26 | --callout-border-rgb: 172, 175, 176; 27 | --card-rgb: 180, 185, 188; 28 | --card-border-rgb: 131, 134, 135; 29 | } 30 | 31 | @media (prefers-color-scheme: dark) { 32 | :root { 33 | --foreground-rgb: 255, 255, 255; 34 | --background-start-rgb: 0, 0, 0; 35 | --background-end-rgb: 0, 0, 0; 36 | 37 | --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0)); 38 | --secondary-glow: linear-gradient( 39 | to bottom right, 40 | rgba(1, 65, 255, 0), 41 | rgba(1, 65, 255, 0), 42 | rgba(1, 65, 255, 0.3) 43 | ); 44 | 45 | --tile-start-rgb: 2, 13, 46; 46 | --tile-end-rgb: 2, 5, 19; 47 | --tile-border: conic-gradient(#ffffff80, #ffffff40, #ffffff30, #ffffff20, #ffffff10, #ffffff10, #ffffff80); 48 | 49 | --callout-rgb: 20, 20, 20; 50 | --callout-border-rgb: 108, 108, 108; 51 | --card-rgb: 100, 100, 100; 52 | --card-border-rgb: 200, 200, 200; 53 | } 54 | } 55 | 56 | * { 57 | box-sizing: border-box; 58 | padding: 0; 59 | margin: 0; 60 | } 61 | 62 | html, 63 | body { 64 | max-width: 100vw; 65 | overflow-x: hidden; 66 | } 67 | 68 | body { 69 | color: rgb(var(--foreground-rgb)); 70 | background: linear-gradient(to bottom, transparent, rgb(var(--background-end-rgb))) rgb(var(--background-start-rgb)); 71 | } 72 | 73 | a { 74 | color: inherit; 75 | text-decoration: none; 76 | } 77 | 78 | @media (prefers-color-scheme: dark) { 79 | html { 80 | color-scheme: dark; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /e2e/src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import { Inter } from "next/font/google"; 3 | import "./globals.css"; 4 | import { ApolloWrapper } from "@/app/ApolloWarapper"; 5 | import { ErrorBoundary } from "react-error-boundary"; 6 | 7 | const inter = Inter({ subsets: ["latin"] }); 8 | 9 | export const metadata: Metadata = { 10 | title: "Create Next App", 11 | description: "Generated by create next app" 12 | }; 13 | 14 | export default function RootLayout({ 15 | children 16 | }: Readonly<{ 17 | children: React.ReactNode; 18 | }>) { 19 | return ( 20 | 21 | 22 | ...}> 23 | {children} 24 | 25 | 26 | 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /e2e/src/app/page.module.css: -------------------------------------------------------------------------------- 1 | .main { 2 | display: flex; 3 | flex-direction: column; 4 | justify-content: space-between; 5 | align-items: center; 6 | padding: 6rem; 7 | min-height: 100vh; 8 | } 9 | 10 | .description { 11 | display: inherit; 12 | justify-content: inherit; 13 | align-items: inherit; 14 | font-size: 0.85rem; 15 | max-width: var(--max-width); 16 | width: 100%; 17 | z-index: 2; 18 | font-family: var(--font-mono); 19 | } 20 | 21 | .description a { 22 | display: flex; 23 | justify-content: center; 24 | align-items: center; 25 | gap: 0.5rem; 26 | } 27 | 28 | .description p { 29 | position: relative; 30 | margin: 0; 31 | padding: 1rem; 32 | background-color: rgba(var(--callout-rgb), 0.5); 33 | border: 1px solid rgba(var(--callout-border-rgb), 0.3); 34 | border-radius: var(--border-radius); 35 | } 36 | 37 | .code { 38 | font-weight: 700; 39 | font-family: var(--font-mono); 40 | } 41 | 42 | .grid { 43 | display: grid; 44 | grid-template-columns: repeat(4, minmax(25%, auto)); 45 | max-width: 100%; 46 | width: var(--max-width); 47 | } 48 | 49 | .card { 50 | padding: 1rem 1.2rem; 51 | border-radius: var(--border-radius); 52 | background: rgba(var(--card-rgb), 0); 53 | border: 1px solid rgba(var(--card-border-rgb), 0); 54 | transition: 55 | background 200ms, 56 | border 200ms; 57 | } 58 | 59 | .card span { 60 | display: inline-block; 61 | transition: transform 200ms; 62 | } 63 | 64 | .card h2 { 65 | font-weight: 600; 66 | margin-bottom: 0.7rem; 67 | } 68 | 69 | .card p { 70 | margin: 0; 71 | opacity: 0.6; 72 | font-size: 0.9rem; 73 | line-height: 1.5; 74 | max-width: 30ch; 75 | text-wrap: balance; 76 | } 77 | 78 | .center { 79 | display: flex; 80 | justify-content: center; 81 | align-items: center; 82 | position: relative; 83 | padding: 4rem 0; 84 | } 85 | 86 | .center::before { 87 | background: var(--secondary-glow); 88 | border-radius: 50%; 89 | width: 480px; 90 | height: 360px; 91 | margin-left: -400px; 92 | } 93 | 94 | .center::after { 95 | background: var(--primary-glow); 96 | width: 240px; 97 | height: 180px; 98 | z-index: -1; 99 | } 100 | 101 | .center::before, 102 | .center::after { 103 | content: ""; 104 | left: 50%; 105 | position: absolute; 106 | filter: blur(45px); 107 | transform: translateZ(0); 108 | } 109 | 110 | .logo { 111 | position: relative; 112 | } 113 | /* Enable hover only on non-touch devices */ 114 | @media (hover: hover) and (pointer: fine) { 115 | .card:hover { 116 | background: rgba(var(--card-rgb), 0.1); 117 | border: 1px solid rgba(var(--card-border-rgb), 0.15); 118 | } 119 | 120 | .card:hover span { 121 | transform: translateX(4px); 122 | } 123 | } 124 | 125 | @media (prefers-reduced-motion) { 126 | .card:hover span { 127 | transform: none; 128 | } 129 | } 130 | 131 | /* Mobile */ 132 | @media (max-width: 700px) { 133 | .content { 134 | padding: 4rem; 135 | } 136 | 137 | .grid { 138 | grid-template-columns: 1fr; 139 | margin-bottom: 120px; 140 | max-width: 320px; 141 | text-align: center; 142 | } 143 | 144 | .card { 145 | padding: 1rem 2.5rem; 146 | } 147 | 148 | .card h2 { 149 | margin-bottom: 0.5rem; 150 | } 151 | 152 | .center { 153 | padding: 8rem 0 6rem; 154 | } 155 | 156 | .center::before { 157 | transform: none; 158 | height: 300px; 159 | } 160 | 161 | .description { 162 | font-size: 0.8rem; 163 | } 164 | 165 | .description a { 166 | padding: 1rem; 167 | } 168 | 169 | .description p, 170 | .description div { 171 | display: flex; 172 | justify-content: center; 173 | position: fixed; 174 | width: 100%; 175 | } 176 | 177 | .description p { 178 | align-items: center; 179 | inset: 0 0 auto; 180 | padding: 2rem 1rem 1.4rem; 181 | border-radius: 0; 182 | border: none; 183 | border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25); 184 | background: linear-gradient(to bottom, rgba(var(--background-start-rgb), 1), rgba(var(--callout-rgb), 0.5)); 185 | background-clip: padding-box; 186 | backdrop-filter: blur(24px); 187 | } 188 | 189 | .description div { 190 | align-items: flex-end; 191 | pointer-events: none; 192 | inset: auto 0 0; 193 | padding: 2rem; 194 | height: 200px; 195 | background: linear-gradient(to bottom, transparent 0%, rgb(var(--background-end-rgb)) 40%); 196 | z-index: 1; 197 | } 198 | } 199 | 200 | /* Tablet and Smaller Desktop */ 201 | @media (min-width: 701px) and (max-width: 1120px) { 202 | .grid { 203 | grid-template-columns: repeat(2, 50%); 204 | } 205 | } 206 | 207 | @media (prefers-color-scheme: dark) { 208 | .vercelLogo { 209 | filter: invert(1); 210 | } 211 | 212 | .logo { 213 | filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70); 214 | } 215 | } 216 | 217 | @keyframes rotate { 218 | from { 219 | transform: rotate(360deg); 220 | } 221 | to { 222 | transform: rotate(0deg); 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /e2e/src/app/page.play.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from "@playwright/test"; 2 | 3 | test("get query and mutate", async ({ page }) => { 4 | await page.goto("http://localhost:3000/"); 5 | 6 | await page.getByTestId("mutate-button").click(); 7 | await expect(page.getByTestId("mutate-result")).toBeVisible(); 8 | }); 9 | -------------------------------------------------------------------------------- /e2e/src/app/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { 3 | useCreateRideHistorySuspenseMutation, 4 | useListRideHistoriesSuspenseQuery 5 | } from "../../generated/typescript/hooks"; 6 | import type { CreateRideHistoryMutationVariables } from "../../generated/typescript/graphql"; 7 | 8 | import { Suspense, useActionState, useEffect, useState } from "react"; 9 | import { GraphQLError } from "graphql/error"; 10 | import type { FetchResult } from "@apollo/client/link/core"; 11 | 12 | class GraphQLNoDataResponseError extends Error { 13 | constructor() { 14 | super("No data"); 15 | } 16 | } 17 | 18 | class GraphQLTopLevelErrors { 19 | constructor(public errors: readonly GraphQLError[]) {} 20 | 21 | get message() { 22 | return this.errors.map((error) => error.message).join("\n"); 23 | } 24 | } 25 | 26 | function getGraphQLMutationResult(result: FetchResult): 27 | | { 28 | ok: true; 29 | data: TData; 30 | } 31 | | { 32 | ok: false; 33 | error: GraphQLTopLevelErrors | GraphQLNoDataResponseError; 34 | } { 35 | if (result.errors) { 36 | return { 37 | ok: false, 38 | error: new GraphQLTopLevelErrors(result.errors) 39 | }; 40 | } 41 | const data = result.data; 42 | if (!data) { 43 | return { 44 | ok: false, 45 | error: new GraphQLNoDataResponseError() 46 | }; 47 | } 48 | return { 49 | ok: true, 50 | data: data 51 | }; 52 | } 53 | 54 | // Error Handling 55 | const DisplayError = ({ errors }: { errors: ReturnType["errors"] }) => { 56 | if (!errors) return null; 57 | // Common Error Case 58 | if (errors instanceof GraphQLTopLevelErrors) { 59 | return
{errors.message}
; 60 | } 61 | if (errors instanceof GraphQLNoDataResponseError) { 62 | return
{errors.message}
; 63 | } 64 | // Application Error Case 65 | return ( 66 |
67 | {errors.map((error) => { 68 | // Handle Validation errors 69 | if ("type" in error) { 70 | switch (error.type) { 71 | case "MissingNameError": 72 | return
{error.message}
; 73 | } 74 | } 75 | // Handle GraphQL errors field 76 | // Note: isTextError does not work narrowing 77 | // https://github.com/microsoft/TypeScript/issues/55766 78 | if ("__typename" in error) { 79 | switch (error.__typename) { 80 | case "TextError": 81 | return
{error.message}
; 82 | case "CreateRideHistoryErrorDetails": 83 | return
{error.message}
; 84 | } 85 | } 86 | return
Unknown Error: {error satisfies never}
; 87 | })} 88 |
89 | ); 90 | }; 91 | 92 | // Validation 93 | type MissingNameError = { 94 | type: "MissingNameError"; 95 | message: string; 96 | }; 97 | 98 | type ValidationError = MissingNameError; 99 | const createCreateRideHistoryMutationVariables = ( 100 | name: string 101 | ): 102 | | { 103 | ok: true; 104 | value: CreateRideHistoryMutationVariables; 105 | } 106 | | { 107 | ok: false; 108 | errors: ValidationError[]; 109 | } => { 110 | if (!name) { 111 | return { 112 | ok: false, 113 | errors: [ 114 | { 115 | type: "MissingNameError", 116 | message: "Name is required" 117 | } 118 | ] 119 | }; 120 | } 121 | return { 122 | ok: true, 123 | value: { 124 | desinationName: name 125 | } 126 | }; 127 | }; 128 | const useMain = () => { 129 | const query = useListRideHistoriesSuspenseQuery(); 130 | const [mutate, { data }] = useCreateRideHistorySuspenseMutation(); 131 | const [errors, onClick, loading] = useActionState(async (_: unknown, __: unknown) => { 132 | const input = createCreateRideHistoryMutationVariables("test"); 133 | if (!input.ok) { 134 | return input.errors; 135 | } 136 | const result = getGraphQLMutationResult( 137 | await mutate({ 138 | variables: input.value 139 | }) 140 | ); 141 | if (!result.ok) { 142 | return result.error; 143 | } 144 | const data = result.data; 145 | if (data.createRideHistory.errors.length > 0) { 146 | return data.createRideHistory.errors; 147 | } 148 | // When mutation is success, you can do something 149 | // TODO: do something 150 | return null; 151 | }, null); 152 | return { query, onClick, data, loading, errors } as const; 153 | }; 154 | const Main = () => { 155 | const { errors, query, onClick, data } = useMain(); 156 | return ( 157 |
158 | Loading...}> 159 |
    160 | {query.data?.rideHistories.map((ride) => ( 161 |
  • 162 |

    {ride.destination.name}

    163 |
  • 164 | ))} 165 |
166 |
167 | 170 |
171 | {errors && } 172 | {data &&

Mutate Success... → {data.createRideHistory.name}

} 173 |
174 |
175 | ); 176 | }; 177 | export default function Home() { 178 | const [isSSR, setIsSSR] = useState(true); 179 | useEffect(() => { 180 | setIsSSR(false); 181 | }, []); 182 | if (isSSR) { 183 | return
SSR...
; 184 | } 185 | return
; 186 | } 187 | -------------------------------------------------------------------------------- /e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "strict": true, 12 | "noEmit": true, 13 | "esModuleInterop": true, 14 | "module": "esnext", 15 | "moduleResolution": "bundler", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "jsx": "preserve", 19 | "incremental": true, 20 | 21 | 22 | "verbatimModuleSyntax": true, 23 | "allowUnusedLabels": false, 24 | "allowUnreachableCode": false, 25 | "exactOptionalPropertyTypes": true, 26 | "noFallthroughCasesInSwitch": true, 27 | "noImplicitOverride": true, 28 | "noImplicitReturns": true, 29 | "noPropertyAccessFromIndexSignature": true, 30 | "noUncheckedIndexedAccess": true, 31 | "noUnusedLocals": true, 32 | "noUnusedParameters": true, 33 | 34 | "plugins": [ 35 | { 36 | "name": "next" 37 | } 38 | ], 39 | "paths": { 40 | "@/*": [ 41 | "./src/*" 42 | ] 43 | } 44 | }, 45 | "include": [ 46 | "next-env.d.ts", 47 | "**/*.ts", 48 | "**/*.tsx", 49 | ".next/types/**/*.ts", 50 | "../test/snapshots/typescript/**/*", 51 | ], 52 | "exclude": [ 53 | "node_modules" 54 | ] 55 | } 56 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/lerna/schemas/lerna-schema.json", 3 | "version": "1.2.2", 4 | "npmClient": "pnpm" 5 | } 6 | -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "targetDefaults": { 3 | "dev": { 4 | "dependsOn": [] 5 | }, 6 | "dev:api": { 7 | "dependsOn": [] 8 | }, 9 | "build": { 10 | "dependsOn": [], 11 | "cache": true, 12 | "outputs": [ 13 | "{projectRoot}/lib", 14 | "{projectRoot}/dist", 15 | "{projectRoot}/out", 16 | "{projectRoot}/.next" 17 | ] 18 | }, 19 | "start": { 20 | "dependsOn": [] 21 | }, 22 | "lint": { 23 | "dependsOn": [] 24 | }, 25 | "format": { 26 | "dependsOn": [] 27 | }, 28 | "prepare": { 29 | "dependsOn": [] 30 | }, 31 | "updateSnapshot": { 32 | "dependsOn": [], 33 | "cache": true, 34 | "outputs": [ 35 | "{projectRoot}/**/snapshots", 36 | "{projectRoot}/**/generated" 37 | ] 38 | }, 39 | "codegen": { 40 | "dependsOn": [], 41 | "cache": true, 42 | "outputs": [ 43 | "{projectRoot}/**/snapshots", 44 | "{projectRoot}/**/generated" 45 | ] 46 | }, 47 | "test": { 48 | "dependsOn": [], 49 | "cache": true, 50 | "outputs": [ 51 | "{projectRoot}/**/snapshots", 52 | "{projectRoot}/**/generated" 53 | ] 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "root", 4 | "version": "1.1.0", 5 | "scripts": { 6 | "build": "lerna run build", 7 | "format": "prettier --write \"**/*.{js,jsx,ts,tsx,css}\"", 8 | "prepare": "git config --local core.hooksPath .githooks", 9 | "updateSnapshot": "lerna run updateSnapshot", 10 | "e2e": "lerna run e2e", 11 | "test": "lerna run test", 12 | "versionup": "lerna version", 13 | "ci:versionup:patch": "lerna version patch --no-push --no-git-tag-version --yes && npm run commit-version", 14 | "ci:versionup:minor": "lerna version minor --no-push --no-git-tag-version --yes && npm run commit-version", 15 | "ci:versionup:major": "lerna version major --no-push --no-git-tag-version --yes && npm run commit-version", 16 | "commit-version": "git add . && git commit -m \"chore(release): v`node -p 'require(\"./lerna.json\").version'`\"", 17 | "release": "lerna publish from-package" 18 | }, 19 | "lint-staged": { 20 | "*.{js,jsx,ts,tsx,css}": [ 21 | "prettier --write" 22 | ] 23 | }, 24 | "prettier": { 25 | "printWidth": 120, 26 | "singleQuote": false, 27 | "tabWidth": 4, 28 | "trailingComma": "none" 29 | }, 30 | "devDependencies": { 31 | "lerna": "^8.1.3", 32 | "prettier": "^3.2.5", 33 | "lint-staged": "^15.2.5" 34 | }, 35 | "packageManager": "pnpm@9.1.4+sha256.30a1801ac4e723779efed13a21f4c39f9eb6c9fbb4ced101bce06b422593d7c9" 36 | } 37 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-type-guards/.gitignore: -------------------------------------------------------------------------------- 1 | ### Generated by gibo (https://github.com/simonwhitaker/gibo) 2 | ### https://raw.github.com/github/gitignore/4488915eec0b3a45b5c63ead28f286819c0917de/Node.gitignore 3 | 4 | # Logs 5 | logs 6 | *.log 7 | npm-debug.log* 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | .pnpm-debug.log* 12 | 13 | # Diagnostic reports (https://nodejs.org/api/report.html) 14 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 15 | 16 | # Runtime data 17 | pids 18 | *.pid 19 | *.seed 20 | *.pid.lock 21 | 22 | # Directory for instrumented libs generated by jscoverage/JSCover 23 | lib-cov 24 | 25 | # Coverage directory used by tools like istanbul 26 | coverage 27 | *.lcov 28 | 29 | # nyc test coverage 30 | .nyc_output 31 | 32 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 33 | .grunt 34 | 35 | # Bower dependency directory (https://bower.io/) 36 | bower_components 37 | 38 | # node-waf configuration 39 | .lock-wscript 40 | 41 | # Compiled binary addons (https://nodejs.org/api/addons.html) 42 | build/Release 43 | 44 | # Dependency directories 45 | node_modules/ 46 | jspm_packages/ 47 | 48 | # Snowpack dependency directory (https://snowpack.dev/) 49 | web_modules/ 50 | 51 | # TypeScript cache 52 | *.tsbuildinfo 53 | 54 | # Optional npm cache directory 55 | .npm 56 | 57 | # Optional eslint cache 58 | .eslintcache 59 | 60 | # Optional stylelint cache 61 | .stylelintcache 62 | 63 | # Microbundle cache 64 | .rpt2_cache/ 65 | .rts2_cache_cjs/ 66 | .rts2_cache_es/ 67 | .rts2_cache_umd/ 68 | 69 | # Optional REPL history 70 | .node_repl_history 71 | 72 | # Output of 'npm pack' 73 | *.tgz 74 | 75 | # Yarn Integrity file 76 | .yarn-integrity 77 | 78 | # dotenv environment variable files 79 | .env 80 | .env.development.local 81 | .env.test.local 82 | .env.production.local 83 | .env.local 84 | 85 | # parcel-bundler cache (https://parceljs.org/) 86 | .cache 87 | .parcel-cache 88 | 89 | # Next.js build output 90 | .next 91 | out 92 | 93 | # Nuxt.js build / generate output 94 | .nuxt 95 | dist 96 | 97 | # Gatsby files 98 | .cache/ 99 | # Comment in the public line in if your project uses Gatsby and not Next.js 100 | # https://nextjs.org/blog/next-9-1#public-directory-support 101 | # public 102 | 103 | # vuepress build output 104 | .vuepress/dist 105 | 106 | # vuepress v2.x temp and cache directory 107 | .temp 108 | .cache 109 | 110 | # Docusaurus cache and generated files 111 | .docusaurus 112 | 113 | # Serverless directories 114 | .serverless/ 115 | 116 | # FuseBox cache 117 | .fusebox/ 118 | 119 | # DynamoDB Local files 120 | .dynamodb/ 121 | 122 | # TernJS port file 123 | .tern-port 124 | 125 | # Stores VSCode versions used for testing VSCode extensions 126 | .vscode-test 127 | 128 | # yarn v2 129 | .yarn/cache 130 | .yarn/unplugged 131 | .yarn/build-state.yml 132 | .yarn/install-state.gz 133 | .pnp.* 134 | ### Generated by gibo (https://github.com/simonwhitaker/gibo) 135 | ### https://raw.github.com/github/gitignore/4488915eec0b3a45b5c63ead28f286819c0917de/Global/JetBrains.gitignore 136 | 137 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 138 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 139 | 140 | # User-specific stuff 141 | .idea/**/workspace.xml 142 | .idea/**/tasks.xml 143 | .idea/**/usage.statistics.xml 144 | .idea/**/dictionaries 145 | .idea/**/shelf 146 | 147 | # AWS User-specific 148 | .idea/**/aws.xml 149 | 150 | # Generated files 151 | .idea/**/contentModel.xml 152 | 153 | # Sensitive or high-churn files 154 | .idea/**/dataSources/ 155 | .idea/**/dataSources.ids 156 | .idea/**/dataSources.local.xml 157 | .idea/**/sqlDataSources.xml 158 | .idea/**/dynamic.xml 159 | .idea/**/uiDesigner.xml 160 | .idea/**/dbnavigator.xml 161 | 162 | # Gradle 163 | .idea/**/gradle.xml 164 | .idea/**/libraries 165 | 166 | # Gradle and Maven with auto-import 167 | # When using Gradle or Maven with auto-import, you should exclude module files, 168 | # since they will be recreated, and may cause churn. Uncomment if using 169 | # auto-import. 170 | # .idea/artifacts 171 | # .idea/compiler.xml 172 | # .idea/jarRepositories.xml 173 | # .idea/modules.xml 174 | # .idea/*.iml 175 | # .idea/modules 176 | # *.iml 177 | # *.ipr 178 | 179 | # CMake 180 | cmake-build-*/ 181 | 182 | # Mongo Explorer plugin 183 | .idea/**/mongoSettings.xml 184 | 185 | # File-based project format 186 | *.iws 187 | 188 | # IntelliJ 189 | out/ 190 | 191 | # mpeltonen/sbt-idea plugin 192 | .idea_modules/ 193 | 194 | # JIRA plugin 195 | atlassian-ide-plugin.xml 196 | 197 | # Cursive Clojure plugin 198 | .idea/replstate.xml 199 | 200 | # SonarLint plugin 201 | .idea/sonarlint/ 202 | 203 | # Crashlytics plugin (for Android Studio and IntelliJ) 204 | com_crashlytics_export_strings.xml 205 | crashlytics.properties 206 | crashlytics-build.properties 207 | fabric.properties 208 | 209 | # Editor-based Rest Client 210 | .idea/httpRequests 211 | 212 | # Android studio 3.1+ serialized cache file 213 | .idea/caches/build_file_checksums.ser 214 | ### Generated by gibo (https://github.com/simonwhitaker/gibo) 215 | ### https://raw.github.com/github/gitignore/4488915eec0b3a45b5c63ead28f286819c0917de/Global/VisualStudioCode.gitignore 216 | 217 | .vscode/* 218 | !.vscode/settings.json 219 | !.vscode/tasks.json 220 | !.vscode/launch.json 221 | !.vscode/extensions.json 222 | !.vscode/*.code-snippets 223 | 224 | # Local History for Visual Studio Code 225 | .history/ 226 | 227 | # Built Visual Studio Code Extensions 228 | *.vsix 229 | # Build files 230 | /lib 231 | /module 232 | 233 | .nx/cache 234 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-type-guards/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 newmo, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-type-guards/README.md: -------------------------------------------------------------------------------- 1 | # @newmo/graphql-codegen-plugin-type-guards 2 | 3 | [GraphQL Codegen Plugin](https://github.com/dotansimha/graphql-code-generator) to create TypeScript type guards for GraphQL types. 4 | 5 | ```graphql 6 | type RideHistory { 7 | "ID of the ride history." 8 | id: ID! 9 | 10 | "Destination of the ride history." 11 | destination: Destination! 12 | } 13 | 14 | enum DestinationType { 15 | "Airport" 16 | AIRPORT 17 | 18 | "Station" 19 | STATION 20 | 21 | "City" 22 | CITY 23 | } 24 | 25 | type Destination { 26 | "ID of the destination." 27 | id: ID! 28 | 29 | "Name of the destination." 30 | name: String! @exampleString(value: "Osaka") 31 | 32 | "Type of the destination." 33 | type: DestinationType! 34 | } 35 | 36 | """ 37 | Error interface 38 | """ 39 | interface Error { 40 | "Error message." 41 | message: String! 42 | "Localized error message." 43 | localizedMessage: String! 44 | } 45 | type TextError implements Error { 46 | "Error message." 47 | message: String! 48 | 49 | "Localized error message." 50 | localizedMessage: String! 51 | } 52 | """ 53 | Specified Error type for createRideHistory mutation. 54 | """ 55 | type CreateRideHistoryErrorDetails implements Error{ 56 | code: Int! 57 | message: String! 58 | localizedMessage: String! 59 | } 60 | union ErrorUnion = TextError | CreateRideHistoryErrorDetails 61 | ``` 62 | 63 | -> 64 | 65 | ```ts 66 | // Type guard for each type 67 | export const isDestination = (field: { __typename?: string; }): field is Destination => field.__typename === 'Destination'; 68 | export const isRideHistory = (field: { __typename?: string; }): field is RideHistory => field.__typename === 'RideHistory'; 69 | // Union type guard 70 | export const isCreateRideHistoryErrorDetails = (field: { __typename?: string; }): field is CreateRideHistoryErrorDetails => field.__typename === 'CreateRideHistoryErrorDetails'; 71 | export const isTextError = (field: { __typename?: string; }): field is TextError => field.__typename === 'TextError'; 72 | export const isErrorUnion = (field: { __typename?: string; }): field is ErrorUnion => { 73 | if(field.__typename === undefined) return false; 74 | return ["CreateRideHistoryErrorDetails","TextError"].includes(field.__typename); 75 | }; 76 | ``` 77 | 78 | ## Install 79 | 80 | Install with [npm](https://www.npmjs.com/): 81 | 82 | npm install @newmo/graphql-codegen-plugin-type-guards --save-dev 83 | # This plugin depends on @graphql-codegen/client-preset 84 | npm install @graphql-codegen/cli @graphql-codegen/client-preset @graphql-typed-document-node/core --save-dev 85 | 86 | ## Usage 87 | 88 | You need to it with [Client preset](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client). 89 | 90 | Your `graphql-codegen.ts` should look like this: 91 | 92 | ```ts 93 | import type { CodegenConfig } from '@graphql-codegen/cli'; 94 | const config: CodegenConfig = { 95 | overwrite: true, 96 | schema: "./api/graphql/api.graphqls", 97 | documents: "./api/graphql/query.graphql", 98 | generates: { 99 | // generates types to api/generated/* 100 | './api/generated/': { 101 | preset: 'client', 102 | config: { 103 | // Required: type guard function depends on non-optional `__typename` field 104 | nonOptionalTypename: true, 105 | }, 106 | plugins: [ 107 | '@newmo/graphql-codegen-plugin-typescript-type-guards', 108 | ], 109 | }, 110 | } 111 | }; 112 | 113 | export default config; 114 | ``` 115 | 116 | Run codegen: 117 | 118 | $ graphql-codegen --config graphql-codegen.ts 119 | 120 | ## Options 121 | 122 | - `namingConvention` (optional): Naming convention for the generated types. Default is `change-case#pascalCase`. 123 | - [Naming Convention](https://the-guild.dev/graphql/codegen/docs/config-reference/naming-convention) 124 | - `typesPrefix` (optional): Prefix for the generated types. 125 | - `typesSuffix` (optional): Suffix for the generated types. 126 | 127 | ## Example output 128 | 129 | See [test/snapshots/typescript/graphql.ts](test/snapshots/typescript/graphql.ts) for example output. 130 | 131 | ## Changelog 132 | 133 | See [Releases page](https://github.com/newmo-oss/graphql-codegen-plugins/releases). 134 | 135 | ## Running tests 136 | 137 | Install devDependencies and Run `npm test`: 138 | 139 | npm test 140 | 141 | ## Contributing 142 | 143 | Pull requests and stars are always welcome. 144 | 145 | For bugs and feature requests, [please create an issue](https://github.com/newmo-oss/graphql-codegen-plugins/issues). 146 | 147 | 1. Fork it! 148 | 2. Create your feature branch: `git checkout -b my-new-feature` 149 | 3. Commit your changes: `git commit -am 'Add some feature'` 150 | 4. Push to the branch: `git push origin my-new-feature` 151 | 5. Submit a pull request :D 152 | 153 | ## License 154 | 155 | MIT © newmo, Inc. 156 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-type-guards/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@newmo/graphql-codegen-plugin-type-guards", 3 | "version": "1.2.1", 4 | "description": "GraphQL Codegen Plugin to create type guards function for TypeScript", 5 | "keywords": [ 6 | "graphql", 7 | "plugin", 8 | "typescript" 9 | ], 10 | "homepage": "https://github.com/newmo-oss/graphql-codegen-plugins", 11 | "bugs": { 12 | "url": "https://github.com/newmo-oss/graphql-codegen-plugins/issues" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/newmo-oss/graphql-codegen-plugins.git" 17 | }, 18 | "license": "MIT", 19 | "author": "newmo, Inc.", 20 | "type": "commonjs", 21 | "main": "lib/graphql-codegen-plugin-type-guards.js", 22 | "files": [ 23 | "lib/" 24 | ], 25 | "workspaces": [ 26 | "./test" 27 | ], 28 | "scripts": { 29 | "build": "tsc", 30 | "format": "prettier --write \"**/*.{js,jsx,ts,tsx,css}\"", 31 | "codegen": "graphql-codegen --config ./test/graphql-codegen.ts", 32 | "updateSnapshot": "npm run build && npm run codegen", 33 | "test": "npm run updateSnapshot && cd test && npm run build" 34 | }, 35 | "peerDependencies": { 36 | "graphql": "^15.0.0 || ^16.0.0" 37 | }, 38 | "dependencies": { 39 | "@graphql-codegen/plugin-helpers": "^5.0.4", 40 | "@graphql-codegen/visitor-plugin-common": "^5.2.0" 41 | }, 42 | "devDependencies": { 43 | "@graphql-codegen/cli": "5.0.0", 44 | "@graphql-codegen/client-preset": "^4.2.4", 45 | "@types/node": "^20.11.29", 46 | "graphql": "^16.8.1", 47 | "typescript": "^5.4.5" 48 | }, 49 | "publishConfig": { 50 | "access": "public" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-type-guards/src/config.ts: -------------------------------------------------------------------------------- 1 | import type { RawTypesConfig } from "@graphql-codegen/visitor-plugin-common"; 2 | 3 | export type RawPluginConfig = { 4 | /** 5 | * The path to the generated types file 6 | * @example 7 | * typeFile: "./graphql.ts" 8 | **/ 9 | typesFile: string; 10 | /** 11 | * Naming convention for the generated types 12 | * GraphQL Codegen Plugin Common Options 13 | **/ 14 | namingConvention?: RawTypesConfig["namingConvention"]; 15 | /** 16 | * Prefix for the generated types 17 | * GraphQL Codegen Plugin Common Options 18 | **/ 19 | typesPrefix?: RawTypesConfig["typesPrefix"]; 20 | /** 21 | * Suffix for the generated types 22 | * GraphQL Codegen Plugin Common Options 23 | **/ 24 | typesSuffix?: RawTypesConfig["typesSuffix"]; 25 | }; 26 | export type PluginConfig = Required; 27 | 28 | export function normalizeConfig(rawConfig: RawPluginConfig): PluginConfig { 29 | return { 30 | typesFile: rawConfig.typesFile, 31 | typesPrefix: rawConfig.typesPrefix ?? "", 32 | typesSuffix: rawConfig.typesSuffix ?? "", 33 | namingConvention: rawConfig.namingConvention ?? "" 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-type-guards/src/convertName.ts: -------------------------------------------------------------------------------- 1 | import { convertFactory } from "@graphql-codegen/visitor-plugin-common"; 2 | import type { ASTNode } from "graphql/index.js"; 3 | import type { PluginConfig } from "./config"; 4 | 5 | /** 6 | * Convert the name of the node to the generated type name 7 | * Client preset use this naming convention 8 | * https://www.npmjs.com/package/@graphql-codegen/client-preset 9 | * @param node 10 | * @param config 11 | */ 12 | export function convertName(node: ASTNode | string, config: PluginConfig): string { 13 | const convert = config.namingConvention 14 | ? convertFactory({ namingConvention: config.namingConvention }) 15 | : convertFactory({}); 16 | let convertedName = ""; 17 | convertedName += config.typesPrefix; 18 | convertedName += convert(node); 19 | convertedName += config.typesSuffix; 20 | return convertedName; 21 | } 22 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-type-guards/src/graphql-codegen-plugin-type-guards.ts: -------------------------------------------------------------------------------- 1 | import { PluginFunction, Types } from "@graphql-codegen/plugin-helpers"; 2 | import { GraphQLSchema, isIntrospectionType, isScalarType, isSpecifiedScalarType, isUnionType } from "graphql"; 3 | import { type GraphQLNamedType, isEnumType, isInputObjectType, isInterfaceType } from "graphql/type/definition"; 4 | import { normalizeConfig, PluginConfig, RawPluginConfig } from "./config"; 5 | import { convertName } from "./convertName"; 6 | 7 | const getUserDefinedTypes = (schema: GraphQLSchema) => { 8 | const typeMap = schema.getTypeMap(); 9 | const allTypeNames = Object.keys(typeMap); 10 | const userDefinedTypes = allTypeNames.filter((typeName) => { 11 | const type = typeMap[typeName]; 12 | if (!type) return; 13 | 14 | // excludes enum - because it does not have __typename 15 | if (isEnumType(type)) return false; 16 | // excludes input type - because it does not have __typename 17 | if (isInputObjectType(type)) return false; 18 | // excludes interface - because it does not have __typename 19 | if (isInterfaceType(type)) return false; 20 | // excludes scalar - because it does not have __typename 21 | if (isScalarType(type)) return false; 22 | // excludes introspection - because it does not have __typename 23 | if (isIntrospectionType(type)) return false; 24 | // excludes specified scalar - because it does not have __typename 25 | if (isSpecifiedScalarType(type)) return false; 26 | 27 | return true; 28 | }); 29 | 30 | return { userDefinedTypes }; 31 | }; 32 | 33 | const getUnionTypes = (type: GraphQLNamedType, config: PluginConfig) => { 34 | // expand union type to A | B | C 35 | if (isUnionType(type)) { 36 | return type.getTypes().map((type) => convertName(type.name, config)); 37 | } 38 | return []; 39 | }; 40 | 41 | export const plugin: PluginFunction = (schema, _, userDefinedConfig) => { 42 | const config = normalizeConfig(userDefinedConfig); 43 | const { userDefinedTypes } = getUserDefinedTypes(schema); 44 | return userDefinedTypes 45 | .map((typeName) => { 46 | // is union type 47 | const typeInfo = schema.getType(typeName); 48 | const convertedTypeName = convertName(typeName, config); 49 | if (isUnionType(typeInfo)) { 50 | const unionTypes = getUnionTypes(typeInfo, config); 51 | return `\ 52 | export const is${convertedTypeName} = (field: { __typename?: string; }): field is ${convertedTypeName} => { 53 | if(field.__typename === undefined) return false; 54 | return ${JSON.stringify(unionTypes)}.includes(field.__typename); 55 | };`; 56 | } 57 | return `export const is${convertedTypeName} = (field: { __typename?: string; }): field is ${convertedTypeName} => field.__typename === '${convertedTypeName}';`; 58 | }) 59 | .join("\n"); 60 | }; 61 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-type-guards/test/api/graphql/api.graphqls: -------------------------------------------------------------------------------- 1 | """ 2 | @exampleString directive specifies an example value for a String field. 3 | This example value is used in the fake data. 4 | 5 | Note: This is for @newmo/graphql-fake-server 6 | """ 7 | directive @exampleString( 8 | """ 9 | The value of the String field. 10 | @exampleString(value: "example") 11 | """ 12 | value: String! 13 | ) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION 14 | 15 | 16 | type Query { 17 | """ 18 | Get the list of destination candidates. 19 | """ 20 | destinationCandidates(text: String!): [Destination!]! 21 | 22 | """ 23 | Get the list of ride histories. 24 | """ 25 | rideHistories: [RideHistory!]! 26 | } 27 | 28 | type RideHistory { 29 | "ID of the ride history." 30 | id: ID! 31 | 32 | "Destination of the ride history." 33 | destination: Destination! 34 | } 35 | 36 | enum DestinationType { 37 | "Airport" 38 | AIRPORT 39 | 40 | "Station" 41 | STATION 42 | 43 | "City" 44 | CITY 45 | } 46 | 47 | type Destination { 48 | "ID of the destination." 49 | id: ID! 50 | 51 | "Name of the destination." 52 | name: String! @exampleString(value: "Osaka") 53 | 54 | "Type of the destination." 55 | type: DestinationType! 56 | } 57 | """ 58 | Error interface 59 | """ 60 | interface Error { 61 | "Error message." 62 | message: String! 63 | "Localized error message." 64 | localizedMessage: String! 65 | } 66 | type TextError implements Error { 67 | "Error message." 68 | message: String! 69 | 70 | "Localized error message." 71 | localizedMessage: String! 72 | } 73 | """ 74 | Specified Error type for createRideHistory mutation. 75 | """ 76 | type CreateRideHistoryErrorDetails implements Error{ 77 | code: Int! 78 | message: String! 79 | localizedMessage: String! 80 | } 81 | union ErrorUnion = TextError | CreateRideHistoryErrorDetails 82 | 83 | input RideHistoryInput { 84 | "Name of the destination." 85 | name: String! @exampleString(value: "Tokyo") 86 | } 87 | type RideHistoryOutput { 88 | "ID of the ride history." 89 | id: ID! 90 | "Name of the destination." 91 | name: String! @exampleString(value: "Tokyo") 92 | 93 | "Error." 94 | errors: [ErrorUnion!]! 95 | } 96 | """ 97 | namingConvention test 98 | - URL 99 | - Create* 100 | """ 101 | type FooURLResource { 102 | "Foo URL" 103 | URL: String! 104 | } 105 | input FooURLInput { 106 | "Foo URL" 107 | URL: String! 108 | } 109 | type FooURLPayload { 110 | "Foo URL" 111 | URL: String! 112 | "Errors" 113 | errors: [CreateFooURLError!]! 114 | } 115 | union CreateFooURLError = CreateFooURLErrorDetail 116 | type CreateFooURLErrorDetail implements Error { 117 | code: CreateFooURLErrorCode! 118 | message: String! 119 | localizedMessage: String! 120 | } 121 | enum CreateFooURLErrorCode { 122 | FAILED_TO_CREATE_FOO_URL 123 | } 124 | 125 | type Mutation { 126 | """ 127 | Create Ride History 128 | """ 129 | createRideHistory(input: RideHistoryInput!): RideHistoryOutput! 130 | 131 | """ 132 | Create Foo URL 133 | """ 134 | createFooURL(input: FooURLInput!): FooURLPayload! 135 | } 136 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-type-guards/test/api/graphql/query.graphql: -------------------------------------------------------------------------------- 1 | query ListDestinationCandidates($text: String!) { 2 | destinationCandidates(text: $text) { 3 | id 4 | name 5 | } 6 | } 7 | 8 | query ListRideHistories { 9 | rideHistories { 10 | id 11 | destination { 12 | id 13 | name 14 | } 15 | } 16 | } 17 | 18 | mutation CreateRideHistory($desinationName: String!) { 19 | createRideHistory(input: { name: $desinationName }){ 20 | id 21 | name 22 | } 23 | } 24 | 25 | mutation CreateFooURL($input: FooURLInput!) { 26 | createFooURL(input: $input) { 27 | URL 28 | errors { 29 | ... on CreateFooURLErrorDetail{ 30 | message 31 | code 32 | localizedMessage 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-type-guards/test/graphql-codegen.ts: -------------------------------------------------------------------------------- 1 | import type { CodegenConfig } from "@graphql-codegen/cli"; 2 | 3 | const plugin = require.resolve("../lib/graphql-codegen-plugin-type-guards.js"); 4 | const config: CodegenConfig = { 5 | overwrite: true, 6 | schema: "./test/api/graphql/api.graphqls", 7 | documents: "./test/api/graphql/query.graphql", 8 | generates: { 9 | "./test/snapshots/typescript/": { 10 | preset: "client", 11 | presetConfig: { 12 | fragmentMasking: { unmaskFunctionName: "getFragmentData" } 13 | }, 14 | plugins: [plugin] 15 | } 16 | } 17 | }; 18 | 19 | export default config; 20 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-type-guards/test/snapshots/typescript/fragment-masking.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { ResultOf, DocumentTypeDecoration, TypedDocumentNode } from '@graphql-typed-document-node/core'; 3 | import { FragmentDefinitionNode } from 'graphql'; 4 | import { Incremental } from './graphql'; 5 | 6 | 7 | export type FragmentType> = TDocumentType extends DocumentTypeDecoration< 8 | infer TType, 9 | any 10 | > 11 | ? [TType] extends [{ ' $fragmentName'?: infer TKey }] 12 | ? TKey extends string 13 | ? { ' $fragmentRefs'?: { [key in TKey]: TType } } 14 | : never 15 | : never 16 | : never; 17 | 18 | // return non-nullable if `fragmentType` is non-nullable 19 | export function getFragmentData( 20 | _documentNode: DocumentTypeDecoration, 21 | fragmentType: FragmentType> 22 | ): TType; 23 | // return nullable if `fragmentType` is nullable 24 | export function getFragmentData( 25 | _documentNode: DocumentTypeDecoration, 26 | fragmentType: FragmentType> | null | undefined 27 | ): TType | null | undefined; 28 | // return array of non-nullable if `fragmentType` is array of non-nullable 29 | export function getFragmentData( 30 | _documentNode: DocumentTypeDecoration, 31 | fragmentType: ReadonlyArray>> 32 | ): ReadonlyArray; 33 | // return array of nullable if `fragmentType` is array of nullable 34 | export function getFragmentData( 35 | _documentNode: DocumentTypeDecoration, 36 | fragmentType: ReadonlyArray>> | null | undefined 37 | ): ReadonlyArray | null | undefined; 38 | export function getFragmentData( 39 | _documentNode: DocumentTypeDecoration, 40 | fragmentType: FragmentType> | ReadonlyArray>> | null | undefined 41 | ): TType | ReadonlyArray | null | undefined { 42 | return fragmentType as any; 43 | } 44 | 45 | 46 | export function makeFragmentData< 47 | F extends DocumentTypeDecoration, 48 | FT extends ResultOf 49 | >(data: FT, _fragment: F): FragmentType { 50 | return data as FragmentType; 51 | } 52 | export function isFragmentReady( 53 | queryNode: DocumentTypeDecoration, 54 | fragmentNode: TypedDocumentNode, 55 | data: FragmentType, any>> | null | undefined 56 | ): data is FragmentType { 57 | const deferredFields = (queryNode as { __meta__?: { deferredFields: Record } }).__meta__ 58 | ?.deferredFields; 59 | 60 | if (!deferredFields) return true; 61 | 62 | const fragDef = fragmentNode.definitions[0] as FragmentDefinitionNode | undefined; 63 | const fragName = fragDef?.name?.value; 64 | 65 | const fields = (fragName && deferredFields[fragName]) || []; 66 | return fields.length > 0 && fields.every(field => data && field in data); 67 | } 68 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-type-guards/test/snapshots/typescript/gql.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import * as types from './graphql'; 3 | import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; 4 | 5 | /** 6 | * Map of all GraphQL operations in the project. 7 | * 8 | * This map has several performance disadvantages: 9 | * 1. It is not tree-shakeable, so it will include all operations in the project. 10 | * 2. It is not minifiable, so the string of a GraphQL query will be multiple times inside the bundle. 11 | * 3. It does not support dead code elimination, so it will add unused operations. 12 | * 13 | * Therefore it is highly recommended to use the babel or swc plugin for production. 14 | */ 15 | const documents = { 16 | "query ListDestinationCandidates($text: String!) {\n destinationCandidates(text: $text) {\n id\n name\n }\n}\n\nquery ListRideHistories {\n rideHistories {\n id\n destination {\n id\n name\n }\n }\n}\n\nmutation CreateRideHistory($desinationName: String!) {\n createRideHistory(input: {name: $desinationName}) {\n id\n name\n }\n}\n\nmutation CreateFooURL($input: FooURLInput!) {\n createFooURL(input: $input) {\n URL\n errors {\n ... on CreateFooURLErrorDetail {\n message\n code\n localizedMessage\n }\n }\n }\n}": types.ListDestinationCandidatesDocument, 17 | }; 18 | 19 | /** 20 | * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. 21 | * 22 | * 23 | * @example 24 | * ```ts 25 | * const query = graphql(`query GetUser($id: ID!) { user(id: $id) { name } }`); 26 | * ``` 27 | * 28 | * The query argument is unknown! 29 | * Please regenerate the types. 30 | */ 31 | export function graphql(source: string): unknown; 32 | 33 | /** 34 | * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. 35 | */ 36 | export function graphql(source: "query ListDestinationCandidates($text: String!) {\n destinationCandidates(text: $text) {\n id\n name\n }\n}\n\nquery ListRideHistories {\n rideHistories {\n id\n destination {\n id\n name\n }\n }\n}\n\nmutation CreateRideHistory($desinationName: String!) {\n createRideHistory(input: {name: $desinationName}) {\n id\n name\n }\n}\n\nmutation CreateFooURL($input: FooURLInput!) {\n createFooURL(input: $input) {\n URL\n errors {\n ... on CreateFooURLErrorDetail {\n message\n code\n localizedMessage\n }\n }\n }\n}"): (typeof documents)["query ListDestinationCandidates($text: String!) {\n destinationCandidates(text: $text) {\n id\n name\n }\n}\n\nquery ListRideHistories {\n rideHistories {\n id\n destination {\n id\n name\n }\n }\n}\n\nmutation CreateRideHistory($desinationName: String!) {\n createRideHistory(input: {name: $desinationName}) {\n id\n name\n }\n}\n\nmutation CreateFooURL($input: FooURLInput!) {\n createFooURL(input: $input) {\n URL\n errors {\n ... on CreateFooURLErrorDetail {\n message\n code\n localizedMessage\n }\n }\n }\n}"]; 37 | 38 | export function graphql(source: string) { 39 | return (documents as any)[source] ?? {}; 40 | } 41 | 42 | export type DocumentType> = TDocumentNode extends DocumentNode< infer TType, any> ? TType : never; -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-type-guards/test/snapshots/typescript/graphql.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; 3 | export type Maybe = T | null; 4 | export type InputMaybe = Maybe; 5 | export type Exact = { [K in keyof T]: T[K] }; 6 | export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; 7 | export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; 8 | export type MakeEmpty = { [_ in K]?: never }; 9 | export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; 10 | /** All built-in and custom scalars, mapped to their actual values */ 11 | export type Scalars = { 12 | ID: { input: string; output: string; } 13 | String: { input: string; output: string; } 14 | Boolean: { input: boolean; output: boolean; } 15 | Int: { input: number; output: number; } 16 | Float: { input: number; output: number; } 17 | }; 18 | 19 | export type CreateFooUrlError = CreateFooUrlErrorDetail; 20 | 21 | export enum CreateFooUrlErrorCode { 22 | FailedToCreateFooUrl = 'FAILED_TO_CREATE_FOO_URL' 23 | } 24 | 25 | export type CreateFooUrlErrorDetail = Error & { 26 | __typename?: 'CreateFooURLErrorDetail'; 27 | code: CreateFooUrlErrorCode; 28 | localizedMessage: Scalars['String']['output']; 29 | message: Scalars['String']['output']; 30 | }; 31 | 32 | /** Specified Error type for createRideHistory mutation. */ 33 | export type CreateRideHistoryErrorDetails = Error & { 34 | __typename?: 'CreateRideHistoryErrorDetails'; 35 | code: Scalars['Int']['output']; 36 | localizedMessage: Scalars['String']['output']; 37 | message: Scalars['String']['output']; 38 | }; 39 | 40 | export type Destination = { 41 | __typename?: 'Destination'; 42 | /** ID of the destination. */ 43 | id: Scalars['ID']['output']; 44 | /** Name of the destination. */ 45 | name: Scalars['String']['output']; 46 | /** Type of the destination. */ 47 | type: DestinationType; 48 | }; 49 | 50 | export enum DestinationType { 51 | /** Airport */ 52 | Airport = 'AIRPORT', 53 | /** City */ 54 | City = 'CITY', 55 | /** Station */ 56 | Station = 'STATION' 57 | } 58 | 59 | /** Error interface */ 60 | export type Error = { 61 | /** Localized error message. */ 62 | localizedMessage: Scalars['String']['output']; 63 | /** Error message. */ 64 | message: Scalars['String']['output']; 65 | }; 66 | 67 | export type ErrorUnion = CreateRideHistoryErrorDetails | TextError; 68 | 69 | export type FooUrlInput = { 70 | /** Foo URL */ 71 | URL: Scalars['String']['input']; 72 | }; 73 | 74 | export type FooUrlPayload = { 75 | __typename?: 'FooURLPayload'; 76 | /** Foo URL */ 77 | URL: Scalars['String']['output']; 78 | /** Errors */ 79 | errors: Array; 80 | }; 81 | 82 | /** 83 | * namingConvention test 84 | * - URL 85 | * - Create* 86 | */ 87 | export type FooUrlResource = { 88 | __typename?: 'FooURLResource'; 89 | /** Foo URL */ 90 | URL: Scalars['String']['output']; 91 | }; 92 | 93 | export type Mutation = { 94 | __typename?: 'Mutation'; 95 | /** Create Foo URL */ 96 | createFooURL: FooUrlPayload; 97 | /** Create Ride History */ 98 | createRideHistory: RideHistoryOutput; 99 | }; 100 | 101 | 102 | export type MutationCreateFooUrlArgs = { 103 | input: FooUrlInput; 104 | }; 105 | 106 | 107 | export type MutationCreateRideHistoryArgs = { 108 | input: RideHistoryInput; 109 | }; 110 | 111 | export type Query = { 112 | __typename?: 'Query'; 113 | /** Get the list of destination candidates. */ 114 | destinationCandidates: Array; 115 | /** Get the list of ride histories. */ 116 | rideHistories: Array; 117 | }; 118 | 119 | 120 | export type QueryDestinationCandidatesArgs = { 121 | text: Scalars['String']['input']; 122 | }; 123 | 124 | export type RideHistory = { 125 | __typename?: 'RideHistory'; 126 | /** Destination of the ride history. */ 127 | destination: Destination; 128 | /** ID of the ride history. */ 129 | id: Scalars['ID']['output']; 130 | }; 131 | 132 | export type RideHistoryInput = { 133 | /** Name of the destination. */ 134 | name: Scalars['String']['input']; 135 | }; 136 | 137 | export type RideHistoryOutput = { 138 | __typename?: 'RideHistoryOutput'; 139 | /** Error. */ 140 | errors: Array; 141 | /** ID of the ride history. */ 142 | id: Scalars['ID']['output']; 143 | /** Name of the destination. */ 144 | name: Scalars['String']['output']; 145 | }; 146 | 147 | export type TextError = Error & { 148 | __typename?: 'TextError'; 149 | /** Localized error message. */ 150 | localizedMessage: Scalars['String']['output']; 151 | /** Error message. */ 152 | message: Scalars['String']['output']; 153 | }; 154 | 155 | export type ListDestinationCandidatesQueryVariables = Exact<{ 156 | text: Scalars['String']['input']; 157 | }>; 158 | 159 | 160 | export type ListDestinationCandidatesQuery = { __typename?: 'Query', destinationCandidates: Array<{ __typename?: 'Destination', id: string, name: string }> }; 161 | 162 | export type ListRideHistoriesQueryVariables = Exact<{ [key: string]: never; }>; 163 | 164 | 165 | export type ListRideHistoriesQuery = { __typename?: 'Query', rideHistories: Array<{ __typename?: 'RideHistory', id: string, destination: { __typename?: 'Destination', id: string, name: string } }> }; 166 | 167 | export type CreateRideHistoryMutationVariables = Exact<{ 168 | desinationName: Scalars['String']['input']; 169 | }>; 170 | 171 | 172 | export type CreateRideHistoryMutation = { __typename?: 'Mutation', createRideHistory: { __typename?: 'RideHistoryOutput', id: string, name: string } }; 173 | 174 | export type CreateFooUrlMutationVariables = Exact<{ 175 | input: FooUrlInput; 176 | }>; 177 | 178 | 179 | export type CreateFooUrlMutation = { __typename?: 'Mutation', createFooURL: { __typename?: 'FooURLPayload', URL: string, errors: Array<{ __typename?: 'CreateFooURLErrorDetail', message: string, code: CreateFooUrlErrorCode, localizedMessage: string }> } }; 180 | 181 | 182 | export const ListDestinationCandidatesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ListDestinationCandidates"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"text"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"destinationCandidates"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"text"},"value":{"kind":"Variable","name":{"kind":"Name","value":"text"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode; 183 | export const ListRideHistoriesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ListRideHistories"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"rideHistories"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"destination"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]} as unknown as DocumentNode; 184 | export const CreateRideHistoryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateRideHistory"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"desinationName"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createRideHistory"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"desinationName"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode; 185 | export const CreateFooUrlDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateFooURL"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"FooURLInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createFooURL"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"URL"}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CreateFooURLErrorDetail"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"localizedMessage"}}]}}]}}]}}]}}]} as unknown as DocumentNode; 186 | export const isCreateFooUrlError = (field: { __typename?: string; }): field is CreateFooUrlError => { 187 | if(field.__typename === undefined) return false; 188 | return ["CreateFooUrlErrorDetail"].includes(field.__typename); 189 | }; 190 | export const isCreateFooUrlErrorDetail = (field: { __typename?: string; }): field is CreateFooUrlErrorDetail => field.__typename === 'CreateFooUrlErrorDetail'; 191 | export const isCreateRideHistoryErrorDetails = (field: { __typename?: string; }): field is CreateRideHistoryErrorDetails => field.__typename === 'CreateRideHistoryErrorDetails'; 192 | export const isDestination = (field: { __typename?: string; }): field is Destination => field.__typename === 'Destination'; 193 | export const isErrorUnion = (field: { __typename?: string; }): field is ErrorUnion => { 194 | if(field.__typename === undefined) return false; 195 | return ["CreateRideHistoryErrorDetails","TextError"].includes(field.__typename); 196 | }; 197 | export const isFooUrlPayload = (field: { __typename?: string; }): field is FooUrlPayload => field.__typename === 'FooUrlPayload'; 198 | export const isFooUrlResource = (field: { __typename?: string; }): field is FooUrlResource => field.__typename === 'FooUrlResource'; 199 | export const isMutation = (field: { __typename?: string; }): field is Mutation => field.__typename === 'Mutation'; 200 | export const isQuery = (field: { __typename?: string; }): field is Query => field.__typename === 'Query'; 201 | export const isRideHistory = (field: { __typename?: string; }): field is RideHistory => field.__typename === 'RideHistory'; 202 | export const isRideHistoryOutput = (field: { __typename?: string; }): field is RideHistoryOutput => field.__typename === 'RideHistoryOutput'; 203 | export const isTextError = (field: { __typename?: string; }): field is TextError => field.__typename === 'TextError'; -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-type-guards/test/snapshots/typescript/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./fragment-masking"; 2 | export * from "./gql"; -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-type-guards/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "ES2022", 15 | /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 16 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 17 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 18 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ 19 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 20 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 21 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 22 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 23 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 24 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 25 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 26 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 27 | 28 | /* Modules */ 29 | "module": "NodeNext", 30 | /* Specify what module code is generated. */ 31 | // "rootDir": "./", /* Specify the root folder within your source files. */ 32 | "moduleResolution": "NodeNext", 33 | /* Specify how TypeScript looks up a file from a given module specifier. */ 34 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 35 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 36 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 37 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 38 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 39 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 40 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 41 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ 42 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ 43 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ 44 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ 45 | // "resolveJsonModule": true, /* Enable importing .json files. */ 46 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ 47 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 48 | 49 | /* JavaScript Support */ 50 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get error from these files. */ 51 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 52 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 53 | 54 | /* Emit */ 55 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 56 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 57 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 58 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 59 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 60 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 61 | "outDir": "./lib/", 62 | /* Specify an output folder for all emitted files. */ 63 | // "removeComments": true, /* Disable emitting comments. */ 64 | // "noEmit": true, /* Disable emitting files from a compilation. */ 65 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 66 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 67 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 68 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 69 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 70 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 71 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 72 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 73 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 74 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 75 | // "noEmitOnError": true, /* Disable emitting files if any type checking error are reported. */ 76 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 77 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 78 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 79 | 80 | /* Interop Constraints */ 81 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 82 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ 83 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 84 | "esModuleInterop": true, 85 | /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 86 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 87 | "forceConsistentCasingInFileNames": true, 88 | /* Ensure that casing is correct in imports. */ 89 | 90 | /* Type Checking */ 91 | "strict": true, 92 | /* Enable all strict type-checking options. */ 93 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 94 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 95 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 96 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 97 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 98 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 99 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 100 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 101 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 102 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 103 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 104 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 105 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 106 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 107 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 108 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 109 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 110 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 111 | 112 | /* Completeness */ 113 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 114 | "skipLibCheck": true 115 | /* Skip type checking all .d.ts files. */ 116 | }, 117 | "include": [ 118 | "src/**/*.ts" 119 | ] 120 | } 121 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-typescript-react-apollo/.gitignore: -------------------------------------------------------------------------------- 1 | ### Generated by gibo (https://github.com/simonwhitaker/gibo) 2 | ### https://raw.github.com/github/gitignore/4488915eec0b3a45b5c63ead28f286819c0917de/Node.gitignore 3 | 4 | # Logs 5 | logs 6 | *.log 7 | npm-debug.log* 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | .pnpm-debug.log* 12 | 13 | # Diagnostic reports (https://nodejs.org/api/report.html) 14 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 15 | 16 | # Runtime data 17 | pids 18 | *.pid 19 | *.seed 20 | *.pid.lock 21 | 22 | # Directory for instrumented libs generated by jscoverage/JSCover 23 | lib-cov 24 | 25 | # Coverage directory used by tools like istanbul 26 | coverage 27 | *.lcov 28 | 29 | # nyc test coverage 30 | .nyc_output 31 | 32 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 33 | .grunt 34 | 35 | # Bower dependency directory (https://bower.io/) 36 | bower_components 37 | 38 | # node-waf configuration 39 | .lock-wscript 40 | 41 | # Compiled binary addons (https://nodejs.org/api/addons.html) 42 | build/Release 43 | 44 | # Dependency directories 45 | node_modules/ 46 | jspm_packages/ 47 | 48 | # Snowpack dependency directory (https://snowpack.dev/) 49 | web_modules/ 50 | 51 | # TypeScript cache 52 | *.tsbuildinfo 53 | 54 | # Optional npm cache directory 55 | .npm 56 | 57 | # Optional eslint cache 58 | .eslintcache 59 | 60 | # Optional stylelint cache 61 | .stylelintcache 62 | 63 | # Microbundle cache 64 | .rpt2_cache/ 65 | .rts2_cache_cjs/ 66 | .rts2_cache_es/ 67 | .rts2_cache_umd/ 68 | 69 | # Optional REPL history 70 | .node_repl_history 71 | 72 | # Output of 'npm pack' 73 | *.tgz 74 | 75 | # Yarn Integrity file 76 | .yarn-integrity 77 | 78 | # dotenv environment variable files 79 | .env 80 | .env.development.local 81 | .env.test.local 82 | .env.production.local 83 | .env.local 84 | 85 | # parcel-bundler cache (https://parceljs.org/) 86 | .cache 87 | .parcel-cache 88 | 89 | # Next.js build output 90 | .next 91 | out 92 | 93 | # Nuxt.js build / generate output 94 | .nuxt 95 | dist 96 | 97 | # Gatsby files 98 | .cache/ 99 | # Comment in the public line in if your project uses Gatsby and not Next.js 100 | # https://nextjs.org/blog/next-9-1#public-directory-support 101 | # public 102 | 103 | # vuepress build output 104 | .vuepress/dist 105 | 106 | # vuepress v2.x temp and cache directory 107 | .temp 108 | .cache 109 | 110 | # Docusaurus cache and generated files 111 | .docusaurus 112 | 113 | # Serverless directories 114 | .serverless/ 115 | 116 | # FuseBox cache 117 | .fusebox/ 118 | 119 | # DynamoDB Local files 120 | .dynamodb/ 121 | 122 | # TernJS port file 123 | .tern-port 124 | 125 | # Stores VSCode versions used for testing VSCode extensions 126 | .vscode-test 127 | 128 | # yarn v2 129 | .yarn/cache 130 | .yarn/unplugged 131 | .yarn/build-state.yml 132 | .yarn/install-state.gz 133 | .pnp.* 134 | ### Generated by gibo (https://github.com/simonwhitaker/gibo) 135 | ### https://raw.github.com/github/gitignore/4488915eec0b3a45b5c63ead28f286819c0917de/Global/JetBrains.gitignore 136 | 137 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 138 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 139 | 140 | # User-specific stuff 141 | .idea/**/workspace.xml 142 | .idea/**/tasks.xml 143 | .idea/**/usage.statistics.xml 144 | .idea/**/dictionaries 145 | .idea/**/shelf 146 | 147 | # AWS User-specific 148 | .idea/**/aws.xml 149 | 150 | # Generated files 151 | .idea/**/contentModel.xml 152 | 153 | # Sensitive or high-churn files 154 | .idea/**/dataSources/ 155 | .idea/**/dataSources.ids 156 | .idea/**/dataSources.local.xml 157 | .idea/**/sqlDataSources.xml 158 | .idea/**/dynamic.xml 159 | .idea/**/uiDesigner.xml 160 | .idea/**/dbnavigator.xml 161 | 162 | # Gradle 163 | .idea/**/gradle.xml 164 | .idea/**/libraries 165 | 166 | # Gradle and Maven with auto-import 167 | # When using Gradle or Maven with auto-import, you should exclude module files, 168 | # since they will be recreated, and may cause churn. Uncomment if using 169 | # auto-import. 170 | # .idea/artifacts 171 | # .idea/compiler.xml 172 | # .idea/jarRepositories.xml 173 | # .idea/modules.xml 174 | # .idea/*.iml 175 | # .idea/modules 176 | # *.iml 177 | # *.ipr 178 | 179 | # CMake 180 | cmake-build-*/ 181 | 182 | # Mongo Explorer plugin 183 | .idea/**/mongoSettings.xml 184 | 185 | # File-based project format 186 | *.iws 187 | 188 | # IntelliJ 189 | out/ 190 | 191 | # mpeltonen/sbt-idea plugin 192 | .idea_modules/ 193 | 194 | # JIRA plugin 195 | atlassian-ide-plugin.xml 196 | 197 | # Cursive Clojure plugin 198 | .idea/replstate.xml 199 | 200 | # SonarLint plugin 201 | .idea/sonarlint/ 202 | 203 | # Crashlytics plugin (for Android Studio and IntelliJ) 204 | com_crashlytics_export_strings.xml 205 | crashlytics.properties 206 | crashlytics-build.properties 207 | fabric.properties 208 | 209 | # Editor-based Rest Client 210 | .idea/httpRequests 211 | 212 | # Android studio 3.1+ serialized cache file 213 | .idea/caches/build_file_checksums.ser 214 | ### Generated by gibo (https://github.com/simonwhitaker/gibo) 215 | ### https://raw.github.com/github/gitignore/4488915eec0b3a45b5c63ead28f286819c0917de/Global/VisualStudioCode.gitignore 216 | 217 | .vscode/* 218 | !.vscode/settings.json 219 | !.vscode/tasks.json 220 | !.vscode/launch.json 221 | !.vscode/extensions.json 222 | !.vscode/*.code-snippets 223 | 224 | # Local History for Visual Studio Code 225 | .history/ 226 | 227 | # Built Visual Studio Code Extensions 228 | *.vsix 229 | # Build files 230 | /lib 231 | /module 232 | 233 | .nx/cache 234 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-typescript-react-apollo/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 newmo, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-typescript-react-apollo/README.md: -------------------------------------------------------------------------------- 1 | # @newmo/graphql-codegen-plugin-typescript-react-apollo 2 | 3 | [GraphQL Codegen Plugin](https://github.com/dotansimha/graphql-code-generator) to create React Hooks using [Apollo's client](https://www.apollographql.com/docs/react/) for [Client preset](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client) 4 | 5 | ## Motivation 6 | 7 | > We now recommend using the client-preset package for a better developer experience and smaller impact on bundle size. 8 | > -- [typescript-react-apollo](https://the-guild.dev/graphql/codegen/plugins/typescript/typescript-react-apollo) is not recommended to use with `@newmo/graphql-codegen-plugin-typescript-react-apollo` because it is not maintained. 9 | 10 | However, [Client preset](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client) does not generate `React Hooks` for `@appllo/client`. 11 | 12 | This plugin generates React Hooks using Apollo's client. 13 | Also, This plugin depends on [Client preset](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client). 14 | 15 | ## Install 16 | 17 | Install with [npm](https://www.npmjs.com/): 18 | 19 | npm install @newmo/graphql-codegen-plugin-typescript-react-apollo --save-dev 20 | # this plugin depends on @graphql-codegen/client-preset 21 | npm install @graphql-codegen/cli @graphql-codegen/client-preset @graphql-typed-document-node/core --save-dev 22 | 23 | ## Usage 24 | 25 | You need to it with [Client preset](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client). 26 | 27 | Your `graphql-codegen.ts` should look like this: 28 | 29 | ```ts 30 | import type { CodegenConfig } from '@graphql-codegen/cli'; 31 | const config: CodegenConfig = { 32 | overwrite: true, 33 | schema: "./api/graphql/api.graphqls", 34 | documents: "./api/graphql/query.graphql", 35 | generates: { 36 | // generates types to api/generated/* 37 | './api/generated/': { 38 | preset: 'client' 39 | }, 40 | // generates React Hooks using Apollo's client to api/generated/hooks.tsx 41 | './api/generated/hooks.tsx': { 42 | 'plugins': [ 43 | '@newmo/graphql-codegen-plugin-typescript-react-apollo' 44 | ], 45 | config: { 46 | // path to generated types 47 | // In this case, it refer './api/generated/graphql.ts' 48 | typesFile: './graphql' 49 | } 50 | } 51 | } 52 | }; 53 | 54 | export default config; 55 | ``` 56 | 57 | Run codegen: 58 | 59 | $ graphql-codegen --config graphql-codegen.ts 60 | 61 | ## Options 62 | 63 | - `namingConvention` (optional): Naming convention for the generated types. Default is `change-case#pascalCase`. 64 | - [Naming Convention](https://the-guild.dev/graphql/codegen/docs/config-reference/naming-convention) 65 | - `typesPrefix` (optional): Prefix for the generated types. 66 | - `typesSuffix` (optional): Suffix for the generated types. 67 | 68 | ## Example output 69 | 70 | See [test/snapshots/typescript](test/snapshots/typescript) for example output. 71 | 72 | ## Changelog 73 | 74 | See [Releases page](https://github.com/newmo-oss/graphql-codegen-plugins/releases). 75 | 76 | ## Running tests 77 | 78 | Install devDependencies and Run `npm test`: 79 | 80 | npm test 81 | 82 | ## Contributing 83 | 84 | Pull requests and stars are always welcome. 85 | 86 | For bugs and feature requests, [please create an issue](https://github.com/newmo-oss/graphql-codegen-plugins/issues). 87 | 88 | 1. Fork it! 89 | 2. Create your feature branch: `git checkout -b my-new-feature` 90 | 3. Commit your changes: `git commit -am 'Add some feature'` 91 | 4. Push to the branch: `git push origin my-new-feature` 92 | 5. Submit a pull request :D 93 | 94 | ## License 95 | 96 | MIT © newmo, Inc. 97 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-typescript-react-apollo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@newmo/graphql-codegen-plugin-typescript-react-apollo", 3 | "version": "1.2.2", 4 | "description": "GraphQL Codegen Plugin to create React Hooks for client preset", 5 | "keywords": [ 6 | "graphql", 7 | "plugin", 8 | "react", 9 | "hook" 10 | ], 11 | "homepage": "https://github.com/newmo-oss/graphql-codegen-plugins", 12 | "bugs": { 13 | "url": "https://github.com/newmo-oss/graphql-codegen-plugins/issues" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/newmo-oss/graphql-codegen-plugins.git" 18 | }, 19 | "license": "MIT", 20 | "author": "newmo, Inc.", 21 | "type": "commonjs", 22 | "main": "lib/graphql-codegen-plugin-typescript-react-apollo.js", 23 | "files": [ 24 | "lib/" 25 | ], 26 | "workspaces": [ 27 | "./test" 28 | ], 29 | "scripts": { 30 | "build": "tsc", 31 | "format": "prettier --write \"**/*.{js,jsx,ts,tsx,css}\"", 32 | "prepare": "git config --local core.hooksPath .githooks", 33 | "codegen": "graphql-codegen --config ./test/graphql-codegen.ts", 34 | "updateSnapshot": "npm run build && npm run codegen", 35 | "test": "npm run updateSnapshot && cd test && npm run build" 36 | }, 37 | "dependencies": { 38 | "@graphql-codegen/plugin-helpers": "^5.0.4", 39 | "@graphql-codegen/visitor-plugin-common": "^5.2.0" 40 | }, 41 | "peerDependencies": { 42 | "graphql": "^15.0.0 || ^16.0.0" 43 | }, 44 | "devDependencies": { 45 | "@graphql-codegen/cli": "5.0.0", 46 | "@graphql-codegen/client-preset": "^4.2.4", 47 | "@types/node": "^20.11.29", 48 | "graphql": "^16.8.2", 49 | "typescript": "^5.4.5" 50 | }, 51 | "publishConfig": { 52 | "access": "public" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-typescript-react-apollo/src/config.ts: -------------------------------------------------------------------------------- 1 | import type { RawTypesConfig } from "@graphql-codegen/visitor-plugin-common"; 2 | 3 | export type RawPluginConfig = { 4 | /** 5 | * The path to the generated types file 6 | * @example 7 | * typeFile: "./graphql.ts" 8 | **/ 9 | typesFile: string; 10 | /** 11 | * Naming convention for the generated types 12 | * GraphQL Codegen Plugin Common Options 13 | **/ 14 | namingConvention?: RawTypesConfig["namingConvention"]; 15 | /** 16 | * Prefix for the generated types 17 | * GraphQL Codegen Plugin Common Options 18 | **/ 19 | typesPrefix?: RawTypesConfig["typesPrefix"]; 20 | /** 21 | * Suffix for the generated types 22 | * GraphQL Codegen Plugin Common Options 23 | **/ 24 | typesSuffix?: RawTypesConfig["typesSuffix"]; 25 | }; 26 | export type PluginConfig = Required; 27 | 28 | export function normalizeConfig(rawConfig: RawPluginConfig): PluginConfig { 29 | return { 30 | typesFile: rawConfig.typesFile, 31 | typesPrefix: rawConfig.typesPrefix ?? "", 32 | typesSuffix: rawConfig.typesSuffix ?? "", 33 | namingConvention: rawConfig.namingConvention ?? "" 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-typescript-react-apollo/src/convertName.ts: -------------------------------------------------------------------------------- 1 | import { convertFactory } from "@graphql-codegen/visitor-plugin-common"; 2 | import type { ASTNode } from "graphql"; 3 | import type { PluginConfig } from "./config"; 4 | 5 | /** 6 | * Convert the name of the node to the generated type name 7 | * Client preset use this naming convention 8 | * https://www.npmjs.com/package/@graphql-codegen/client-preset 9 | * @param node 10 | * @param config 11 | */ 12 | export function convertName(node: ASTNode | string, config: PluginConfig): string { 13 | const convert = config.namingConvention 14 | ? convertFactory({ namingConvention: config.namingConvention }) 15 | : convertFactory({}); 16 | let convertedName = ""; 17 | convertedName += config.typesPrefix; 18 | convertedName += convert(node); 19 | convertedName += config.typesSuffix; 20 | return convertedName; 21 | } 22 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-typescript-react-apollo/src/graphql-codegen-plugin-typescript-react-apollo.ts: -------------------------------------------------------------------------------- 1 | import type { CodegenPlugin } from "@graphql-codegen/plugin-helpers"; 2 | import { normalizeConfig, RawPluginConfig } from "./config"; 3 | import { convertName } from "./convertName"; 4 | const plugin: CodegenPlugin = { 5 | plugin(schema, documents, rawConfig, _info) { 6 | const config = normalizeConfig(rawConfig); 7 | // need to support mutation, query, subscription 8 | const generateSuspenseQuery = (name: string) => { 9 | return `export function use${name}SuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions<${name}Query, ${name}QueryVariables>): Apollo.UseSuspenseQueryResult<${name}Query, ${name}QueryVariables> { 10 | const options = { ...baseOptions }; 11 | return Apollo.useSuspenseQuery<${name}Query, ${name}QueryVariables>(${name}Document, options); 12 | }`; 13 | }; 14 | const generateSuspenseMutation = (name: string) => { 15 | return `export function use${name}SuspenseMutation(baseOptions?: Apollo.MutationHookOptions<${name}Mutation, ${name}MutationVariables>): Apollo.MutationTuple<${name}Mutation, ${name}MutationVariables> { 16 | const options = { ...baseOptions }; 17 | return Apollo.useMutation<${name}Mutation, ${name}MutationVariables>(${name}Document, options); 18 | }`; 19 | }; 20 | const importQueryIdentifierName = (documentName: string) => { 21 | return `import { ${documentName}Document } from '${config.typesFile}'; 22 | import type { ${documentName}Query, ${documentName}QueryVariables } from '${config.typesFile}';`; 23 | }; 24 | const importMutationIdentifierName = (documentName: string) => { 25 | return `import { ${documentName}Document } from '${config.typesFile}'; 26 | import type { ${documentName}Mutation, ${documentName}MutationVariables } from '${config.typesFile}';`; 27 | }; 28 | return `/* eslint-disable */ 29 | // This file was generated by a @newmo/graphql-codegen-plugin-typescript-react-apollo 30 | import * as Apollo from '@apollo/client'; 31 | ${documents 32 | .flatMap((document) => { 33 | return document.document?.definitions?.map((definition) => { 34 | // query 35 | if (definition.kind === "OperationDefinition" && definition.operation === "query" && definition.name) { 36 | return importQueryIdentifierName(convertName(definition.name.value, config)); 37 | } else if ( 38 | definition.kind === "OperationDefinition" && 39 | definition.operation === "mutation" && 40 | definition.name 41 | ) { 42 | return importMutationIdentifierName(convertName(definition.name.value, config)); 43 | } 44 | }); 45 | }) 46 | .join("\n")} 47 | ${documents 48 | .flatMap((document) => { 49 | return document.document?.definitions?.map((definition) => { 50 | // query 51 | if (definition.kind === "OperationDefinition" && definition.operation === "query" && definition.name) { 52 | return generateSuspenseQuery(convertName(definition.name.value, config)); 53 | } else if ( 54 | definition.kind === "OperationDefinition" && 55 | definition.operation === "mutation" && 56 | definition.name 57 | ) { 58 | return generateSuspenseMutation(convertName(definition.name.value, config)); 59 | } 60 | }); 61 | }) 62 | .join("\n")} 63 | `; 64 | } 65 | }; 66 | // GraphQL Codegen Plugin requires CommonJS export 67 | module.exports = plugin; 68 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-typescript-react-apollo/test/api/graphql/api.graphqls: -------------------------------------------------------------------------------- 1 | """ 2 | @exampleString directive specifies an example value for a String field. 3 | This example value is used in the fake data. 4 | 5 | Note: This is for @newmo/graphql-fake-server 6 | """ 7 | directive @exampleString( 8 | """ 9 | The value of the String field. 10 | @exampleString(value: "example") 11 | """ 12 | value: String! 13 | ) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION 14 | 15 | 16 | type Query { 17 | """ 18 | Get the list of destination candidates. 19 | """ 20 | destinationCandidates(text: String!): [Destination!]! 21 | 22 | """ 23 | Get the list of ride histories. 24 | """ 25 | rideHistories: [RideHistory!]! 26 | } 27 | 28 | type RideHistory { 29 | "ID of the ride history." 30 | id: ID! 31 | 32 | "Destination of the ride history." 33 | destination: Destination! 34 | } 35 | 36 | enum DestinationType { 37 | "Airport" 38 | AIRPORT 39 | 40 | "Station" 41 | STATION 42 | 43 | "City" 44 | CITY 45 | } 46 | 47 | type Destination { 48 | "ID of the destination." 49 | id: ID! 50 | 51 | "Name of the destination." 52 | name: String! @exampleString(value: "Osaka") 53 | 54 | "Type of the destination." 55 | type: DestinationType! 56 | } 57 | """ 58 | Error interface 59 | """ 60 | interface Error { 61 | "Error message." 62 | message: String! 63 | "Localized error message." 64 | localizedMessage: String! 65 | } 66 | type TextError implements Error { 67 | "Error message." 68 | message: String! 69 | 70 | "Localized error message." 71 | localizedMessage: String! 72 | } 73 | """ 74 | Specified Error type for createRideHistory mutation. 75 | """ 76 | type CreateRideHistoryErrorDetails implements Error{ 77 | code: Int! 78 | message: String! 79 | localizedMessage: String! 80 | } 81 | union ErrorUnion = TextError | CreateRideHistoryErrorDetails 82 | 83 | input RideHistoryInput { 84 | "Name of the destination." 85 | name: String! @exampleString(value: "Tokyo") 86 | } 87 | type RideHistoryOutput { 88 | "ID of the ride history." 89 | id: ID! 90 | "Name of the destination." 91 | name: String! @exampleString(value: "Tokyo") 92 | 93 | "Error." 94 | errors: [ErrorUnion!]! 95 | } 96 | """ 97 | namingConvention test 98 | - URL 99 | - Create* 100 | """ 101 | type FooURLResource { 102 | "Foo URL" 103 | URL: String! 104 | } 105 | input FooURLInput { 106 | "Foo URL" 107 | URL: String! 108 | } 109 | type FooURLPayload { 110 | "Foo URL" 111 | URL: String! 112 | "Errors" 113 | errors: [CreateFooURLError!]! 114 | } 115 | union CreateFooURLError = CreateFooURLErrorDetail 116 | type CreateFooURLErrorDetail implements Error { 117 | code: CreateFooURLErrorCode! 118 | message: String! 119 | localizedMessage: String! 120 | } 121 | enum CreateFooURLErrorCode { 122 | FAILED_TO_CREATE_FOO_URL 123 | } 124 | 125 | type Mutation { 126 | """ 127 | Create Ride History 128 | """ 129 | createRideHistory(input: RideHistoryInput!): RideHistoryOutput! 130 | 131 | """ 132 | Create Foo URL 133 | """ 134 | createFooURL(input: FooURLInput!): FooURLPayload! 135 | } 136 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-typescript-react-apollo/test/api/graphql/query.graphql: -------------------------------------------------------------------------------- 1 | query ListDestinationCandidates($text: String!) { 2 | destinationCandidates(text: $text) { 3 | id 4 | name 5 | } 6 | } 7 | 8 | query ListRideHistories { 9 | rideHistories { 10 | id 11 | destination { 12 | id 13 | name 14 | } 15 | } 16 | } 17 | 18 | mutation CreateRideHistory($desinationName: String!) { 19 | createRideHistory(input: { name: $desinationName }){ 20 | id 21 | name 22 | } 23 | } 24 | 25 | mutation CreateFooURL($input: FooURLInput!) { 26 | createFooURL(input: $input) { 27 | URL 28 | errors { 29 | ... on CreateFooURLErrorDetail{ 30 | message 31 | code 32 | localizedMessage 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-typescript-react-apollo/test/graphql-codegen.ts: -------------------------------------------------------------------------------- 1 | import type { CodegenConfig } from "@graphql-codegen/cli"; 2 | 3 | const plugin = require.resolve("../lib/graphql-codegen-plugin-typescript-react-apollo.js"); 4 | const config: CodegenConfig = { 5 | overwrite: true, 6 | schema: "./test/api/graphql/api.graphqls", 7 | documents: "./test/api/graphql/query.graphql", 8 | generates: { 9 | "./test/snapshots/typescript/": { 10 | preset: "client", 11 | presetConfig: { 12 | fragmentMasking: { unmaskFunctionName: "getFragmentData" } 13 | }, 14 | documentTransforms: [] 15 | }, 16 | "./test/snapshots/typescript/hooks.tsx": { 17 | plugins: [plugin], 18 | config: { 19 | typesFile: "./graphql" // required 20 | } 21 | } 22 | } 23 | }; 24 | 25 | export default config; 26 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-typescript-react-apollo/test/snapshots/typescript/fragment-masking.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { ResultOf, DocumentTypeDecoration, TypedDocumentNode } from '@graphql-typed-document-node/core'; 3 | import { FragmentDefinitionNode } from 'graphql'; 4 | import { Incremental } from './graphql'; 5 | 6 | 7 | export type FragmentType> = TDocumentType extends DocumentTypeDecoration< 8 | infer TType, 9 | any 10 | > 11 | ? [TType] extends [{ ' $fragmentName'?: infer TKey }] 12 | ? TKey extends string 13 | ? { ' $fragmentRefs'?: { [key in TKey]: TType } } 14 | : never 15 | : never 16 | : never; 17 | 18 | // return non-nullable if `fragmentType` is non-nullable 19 | export function getFragmentData( 20 | _documentNode: DocumentTypeDecoration, 21 | fragmentType: FragmentType> 22 | ): TType; 23 | // return nullable if `fragmentType` is nullable 24 | export function getFragmentData( 25 | _documentNode: DocumentTypeDecoration, 26 | fragmentType: FragmentType> | null | undefined 27 | ): TType | null | undefined; 28 | // return array of non-nullable if `fragmentType` is array of non-nullable 29 | export function getFragmentData( 30 | _documentNode: DocumentTypeDecoration, 31 | fragmentType: ReadonlyArray>> 32 | ): ReadonlyArray; 33 | // return array of nullable if `fragmentType` is array of nullable 34 | export function getFragmentData( 35 | _documentNode: DocumentTypeDecoration, 36 | fragmentType: ReadonlyArray>> | null | undefined 37 | ): ReadonlyArray | null | undefined; 38 | export function getFragmentData( 39 | _documentNode: DocumentTypeDecoration, 40 | fragmentType: FragmentType> | ReadonlyArray>> | null | undefined 41 | ): TType | ReadonlyArray | null | undefined { 42 | return fragmentType as any; 43 | } 44 | 45 | 46 | export function makeFragmentData< 47 | F extends DocumentTypeDecoration, 48 | FT extends ResultOf 49 | >(data: FT, _fragment: F): FragmentType { 50 | return data as FragmentType; 51 | } 52 | export function isFragmentReady( 53 | queryNode: DocumentTypeDecoration, 54 | fragmentNode: TypedDocumentNode, 55 | data: FragmentType, any>> | null | undefined 56 | ): data is FragmentType { 57 | const deferredFields = (queryNode as { __meta__?: { deferredFields: Record } }).__meta__ 58 | ?.deferredFields; 59 | 60 | if (!deferredFields) return true; 61 | 62 | const fragDef = fragmentNode.definitions[0] as FragmentDefinitionNode | undefined; 63 | const fragName = fragDef?.name?.value; 64 | 65 | const fields = (fragName && deferredFields[fragName]) || []; 66 | return fields.length > 0 && fields.every(field => data && field in data); 67 | } 68 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-typescript-react-apollo/test/snapshots/typescript/gql.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import * as types from './graphql'; 3 | import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; 4 | 5 | /** 6 | * Map of all GraphQL operations in the project. 7 | * 8 | * This map has several performance disadvantages: 9 | * 1. It is not tree-shakeable, so it will include all operations in the project. 10 | * 2. It is not minifiable, so the string of a GraphQL query will be multiple times inside the bundle. 11 | * 3. It does not support dead code elimination, so it will add unused operations. 12 | * 13 | * Therefore it is highly recommended to use the babel or swc plugin for production. 14 | */ 15 | const documents = { 16 | "query ListDestinationCandidates($text: String!) {\n destinationCandidates(text: $text) {\n id\n name\n }\n}\n\nquery ListRideHistories {\n rideHistories {\n id\n destination {\n id\n name\n }\n }\n}\n\nmutation CreateRideHistory($desinationName: String!) {\n createRideHistory(input: {name: $desinationName}) {\n id\n name\n }\n}\n\nmutation CreateFooURL($input: FooURLInput!) {\n createFooURL(input: $input) {\n URL\n errors {\n ... on CreateFooURLErrorDetail {\n message\n code\n localizedMessage\n }\n }\n }\n}": types.ListDestinationCandidatesDocument, 17 | }; 18 | 19 | /** 20 | * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. 21 | * 22 | * 23 | * @example 24 | * ```ts 25 | * const query = graphql(`query GetUser($id: ID!) { user(id: $id) { name } }`); 26 | * ``` 27 | * 28 | * The query argument is unknown! 29 | * Please regenerate the types. 30 | */ 31 | export function graphql(source: string): unknown; 32 | 33 | /** 34 | * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. 35 | */ 36 | export function graphql(source: "query ListDestinationCandidates($text: String!) {\n destinationCandidates(text: $text) {\n id\n name\n }\n}\n\nquery ListRideHistories {\n rideHistories {\n id\n destination {\n id\n name\n }\n }\n}\n\nmutation CreateRideHistory($desinationName: String!) {\n createRideHistory(input: {name: $desinationName}) {\n id\n name\n }\n}\n\nmutation CreateFooURL($input: FooURLInput!) {\n createFooURL(input: $input) {\n URL\n errors {\n ... on CreateFooURLErrorDetail {\n message\n code\n localizedMessage\n }\n }\n }\n}"): (typeof documents)["query ListDestinationCandidates($text: String!) {\n destinationCandidates(text: $text) {\n id\n name\n }\n}\n\nquery ListRideHistories {\n rideHistories {\n id\n destination {\n id\n name\n }\n }\n}\n\nmutation CreateRideHistory($desinationName: String!) {\n createRideHistory(input: {name: $desinationName}) {\n id\n name\n }\n}\n\nmutation CreateFooURL($input: FooURLInput!) {\n createFooURL(input: $input) {\n URL\n errors {\n ... on CreateFooURLErrorDetail {\n message\n code\n localizedMessage\n }\n }\n }\n}"]; 37 | 38 | export function graphql(source: string) { 39 | return (documents as any)[source] ?? {}; 40 | } 41 | 42 | export type DocumentType> = TDocumentNode extends DocumentNode< infer TType, any> ? TType : never; -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-typescript-react-apollo/test/snapshots/typescript/graphql.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; 3 | export type Maybe = T | null; 4 | export type InputMaybe = Maybe; 5 | export type Exact = { [K in keyof T]: T[K] }; 6 | export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; 7 | export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; 8 | export type MakeEmpty = { [_ in K]?: never }; 9 | export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; 10 | /** All built-in and custom scalars, mapped to their actual values */ 11 | export type Scalars = { 12 | ID: { input: string; output: string; } 13 | String: { input: string; output: string; } 14 | Boolean: { input: boolean; output: boolean; } 15 | Int: { input: number; output: number; } 16 | Float: { input: number; output: number; } 17 | }; 18 | 19 | export type CreateFooUrlError = CreateFooUrlErrorDetail; 20 | 21 | export enum CreateFooUrlErrorCode { 22 | FailedToCreateFooUrl = 'FAILED_TO_CREATE_FOO_URL' 23 | } 24 | 25 | export type CreateFooUrlErrorDetail = Error & { 26 | __typename?: 'CreateFooURLErrorDetail'; 27 | code: CreateFooUrlErrorCode; 28 | localizedMessage: Scalars['String']['output']; 29 | message: Scalars['String']['output']; 30 | }; 31 | 32 | /** Specified Error type for createRideHistory mutation. */ 33 | export type CreateRideHistoryErrorDetails = Error & { 34 | __typename?: 'CreateRideHistoryErrorDetails'; 35 | code: Scalars['Int']['output']; 36 | localizedMessage: Scalars['String']['output']; 37 | message: Scalars['String']['output']; 38 | }; 39 | 40 | export type Destination = { 41 | __typename?: 'Destination'; 42 | /** ID of the destination. */ 43 | id: Scalars['ID']['output']; 44 | /** Name of the destination. */ 45 | name: Scalars['String']['output']; 46 | /** Type of the destination. */ 47 | type: DestinationType; 48 | }; 49 | 50 | export enum DestinationType { 51 | /** Airport */ 52 | Airport = 'AIRPORT', 53 | /** City */ 54 | City = 'CITY', 55 | /** Station */ 56 | Station = 'STATION' 57 | } 58 | 59 | /** Error interface */ 60 | export type Error = { 61 | /** Localized error message. */ 62 | localizedMessage: Scalars['String']['output']; 63 | /** Error message. */ 64 | message: Scalars['String']['output']; 65 | }; 66 | 67 | export type ErrorUnion = CreateRideHistoryErrorDetails | TextError; 68 | 69 | export type FooUrlInput = { 70 | /** Foo URL */ 71 | URL: Scalars['String']['input']; 72 | }; 73 | 74 | export type FooUrlPayload = { 75 | __typename?: 'FooURLPayload'; 76 | /** Foo URL */ 77 | URL: Scalars['String']['output']; 78 | /** Errors */ 79 | errors: Array; 80 | }; 81 | 82 | /** 83 | * namingConvention test 84 | * - URL 85 | * - Create* 86 | */ 87 | export type FooUrlResource = { 88 | __typename?: 'FooURLResource'; 89 | /** Foo URL */ 90 | URL: Scalars['String']['output']; 91 | }; 92 | 93 | export type Mutation = { 94 | __typename?: 'Mutation'; 95 | /** Create Foo URL */ 96 | createFooURL: FooUrlPayload; 97 | /** Create Ride History */ 98 | createRideHistory: RideHistoryOutput; 99 | }; 100 | 101 | 102 | export type MutationCreateFooUrlArgs = { 103 | input: FooUrlInput; 104 | }; 105 | 106 | 107 | export type MutationCreateRideHistoryArgs = { 108 | input: RideHistoryInput; 109 | }; 110 | 111 | export type Query = { 112 | __typename?: 'Query'; 113 | /** Get the list of destination candidates. */ 114 | destinationCandidates: Array; 115 | /** Get the list of ride histories. */ 116 | rideHistories: Array; 117 | }; 118 | 119 | 120 | export type QueryDestinationCandidatesArgs = { 121 | text: Scalars['String']['input']; 122 | }; 123 | 124 | export type RideHistory = { 125 | __typename?: 'RideHistory'; 126 | /** Destination of the ride history. */ 127 | destination: Destination; 128 | /** ID of the ride history. */ 129 | id: Scalars['ID']['output']; 130 | }; 131 | 132 | export type RideHistoryInput = { 133 | /** Name of the destination. */ 134 | name: Scalars['String']['input']; 135 | }; 136 | 137 | export type RideHistoryOutput = { 138 | __typename?: 'RideHistoryOutput'; 139 | /** Error. */ 140 | errors: Array; 141 | /** ID of the ride history. */ 142 | id: Scalars['ID']['output']; 143 | /** Name of the destination. */ 144 | name: Scalars['String']['output']; 145 | }; 146 | 147 | export type TextError = Error & { 148 | __typename?: 'TextError'; 149 | /** Localized error message. */ 150 | localizedMessage: Scalars['String']['output']; 151 | /** Error message. */ 152 | message: Scalars['String']['output']; 153 | }; 154 | 155 | export type ListDestinationCandidatesQueryVariables = Exact<{ 156 | text: Scalars['String']['input']; 157 | }>; 158 | 159 | 160 | export type ListDestinationCandidatesQuery = { __typename?: 'Query', destinationCandidates: Array<{ __typename?: 'Destination', id: string, name: string }> }; 161 | 162 | export type ListRideHistoriesQueryVariables = Exact<{ [key: string]: never; }>; 163 | 164 | 165 | export type ListRideHistoriesQuery = { __typename?: 'Query', rideHistories: Array<{ __typename?: 'RideHistory', id: string, destination: { __typename?: 'Destination', id: string, name: string } }> }; 166 | 167 | export type CreateRideHistoryMutationVariables = Exact<{ 168 | desinationName: Scalars['String']['input']; 169 | }>; 170 | 171 | 172 | export type CreateRideHistoryMutation = { __typename?: 'Mutation', createRideHistory: { __typename?: 'RideHistoryOutput', id: string, name: string } }; 173 | 174 | export type CreateFooUrlMutationVariables = Exact<{ 175 | input: FooUrlInput; 176 | }>; 177 | 178 | 179 | export type CreateFooUrlMutation = { __typename?: 'Mutation', createFooURL: { __typename?: 'FooURLPayload', URL: string, errors: Array<{ __typename?: 'CreateFooURLErrorDetail', message: string, code: CreateFooUrlErrorCode, localizedMessage: string }> } }; 180 | 181 | 182 | export const ListDestinationCandidatesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ListDestinationCandidates"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"text"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"destinationCandidates"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"text"},"value":{"kind":"Variable","name":{"kind":"Name","value":"text"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode; 183 | export const ListRideHistoriesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ListRideHistories"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"rideHistories"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"destination"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]} as unknown as DocumentNode; 184 | export const CreateRideHistoryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateRideHistory"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"desinationName"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createRideHistory"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"desinationName"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode; 185 | export const CreateFooUrlDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateFooURL"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"FooURLInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createFooURL"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"URL"}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CreateFooURLErrorDetail"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"localizedMessage"}}]}}]}}]}}]}}]} as unknown as DocumentNode; -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-typescript-react-apollo/test/snapshots/typescript/hooks.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // This file was generated by a @newmo/graphql-codegen-plugin-typescript-react-apollo 3 | import * as Apollo from '@apollo/client'; 4 | import { ListDestinationCandidatesDocument } from './graphql'; 5 | import type { ListDestinationCandidatesQuery, ListDestinationCandidatesQueryVariables } from './graphql'; 6 | import { ListRideHistoriesDocument } from './graphql'; 7 | import type { ListRideHistoriesQuery, ListRideHistoriesQueryVariables } from './graphql'; 8 | import { CreateRideHistoryDocument } from './graphql'; 9 | import type { CreateRideHistoryMutation, CreateRideHistoryMutationVariables } from './graphql'; 10 | import { CreateFooUrlDocument } from './graphql'; 11 | import type { CreateFooUrlMutation, CreateFooUrlMutationVariables } from './graphql'; 12 | export function useListDestinationCandidatesSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions): Apollo.UseSuspenseQueryResult { 13 | const options = { ...baseOptions }; 14 | return Apollo.useSuspenseQuery(ListDestinationCandidatesDocument, options); 15 | } 16 | export function useListRideHistoriesSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions): Apollo.UseSuspenseQueryResult { 17 | const options = { ...baseOptions }; 18 | return Apollo.useSuspenseQuery(ListRideHistoriesDocument, options); 19 | } 20 | export function useCreateRideHistorySuspenseMutation(baseOptions?: Apollo.MutationHookOptions): Apollo.MutationTuple { 21 | const options = { ...baseOptions }; 22 | return Apollo.useMutation(CreateRideHistoryDocument, options); 23 | } 24 | export function useCreateFooUrlSuspenseMutation(baseOptions?: Apollo.MutationHookOptions): Apollo.MutationTuple { 25 | const options = { ...baseOptions }; 26 | return Apollo.useMutation(CreateFooUrlDocument, options); 27 | } 28 | -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-typescript-react-apollo/test/snapshots/typescript/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./fragment-masking"; 2 | export * from "./gql"; -------------------------------------------------------------------------------- /packages/@newmo/graphql-codegen-plugin-typescript-react-apollo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "ES2022", 15 | /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 16 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 17 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 18 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ 19 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 20 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 21 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 22 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 23 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 24 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 25 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 26 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 27 | 28 | /* Modules */ 29 | "module": "NodeNext", 30 | /* Specify what module code is generated. */ 31 | // "rootDir": "./", /* Specify the root folder within your source files. */ 32 | "moduleResolution": "NodeNext", 33 | /* Specify how TypeScript looks up a file from a given module specifier. */ 34 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 35 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 36 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 37 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 38 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 39 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 40 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 41 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ 42 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ 43 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ 44 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ 45 | // "resolveJsonModule": true, /* Enable importing .json files. */ 46 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ 47 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 48 | 49 | /* JavaScript Support */ 50 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get error from these files. */ 51 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 52 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 53 | 54 | /* Emit */ 55 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 56 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 57 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 58 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 59 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 60 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 61 | "outDir": "./lib/", 62 | /* Specify an output folder for all emitted files. */ 63 | // "removeComments": true, /* Disable emitting comments. */ 64 | // "noEmit": true, /* Disable emitting files from a compilation. */ 65 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 66 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 67 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 68 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 69 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 70 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 71 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 72 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 73 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 74 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 75 | // "noEmitOnError": true, /* Disable emitting files if any type checking error are reported. */ 76 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 77 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 78 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 79 | 80 | /* Interop Constraints */ 81 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 82 | "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ 83 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 84 | "esModuleInterop": true, 85 | /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 86 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 87 | "forceConsistentCasingInFileNames": true, 88 | /* Ensure that casing is correct in imports. */ 89 | 90 | /* Type Checking */ 91 | "strict": true, 92 | /* Enable all strict type-checking options. */ 93 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 94 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 95 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 96 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 97 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 98 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 99 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 100 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 101 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 102 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 103 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 104 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 105 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 106 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 107 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 108 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 109 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 110 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 111 | 112 | /* Completeness */ 113 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 114 | "skipLibCheck": true 115 | /* Skip type checking all .d.ts files. */ 116 | }, 117 | "include": [ 118 | "src/**/*.ts" 119 | ] 120 | } 121 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "packages/@newmo/*" 3 | - "e2e" 4 | 5 | --------------------------------------------------------------------------------