Skip to content

Commit

Permalink
feat(cli): generate from introspection (#1014)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonkuhrt authored Aug 4, 2024
1 parent ddf27ed commit 8e12e0b
Show file tree
Hide file tree
Showing 21 changed files with 566 additions and 68 deletions.
2 changes: 1 addition & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import configPrisma from 'eslint-config-prisma'
import tsEslint from 'typescript-eslint'

export default tsEslint.config({
ignores: ['**/build/**/*', 'eslint.config.js', 'vite.config.ts', '**/generated/**/*'],
ignores: ['**/build/**/*', 'eslint.config.js', 'vite.config.ts', '**/generated/**/*', '**/generated-clients/**/*'],
extends: configPrisma,
languageOptions: {
parserOptions: {
Expand Down
39 changes: 17 additions & 22 deletions examples/config-fetch.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,23 @@
/* eslint-disable */

import { gql, Graffle } from '../src/entrypoints/alpha/main.js'
import { CountriesClient } from './generated-clients/countries/__.js'

const request = Graffle.create({ schema: `https://countries.trevorblades.com/graphql` }).use({
name: `CustomFetch`,
anyware: async ({ exchange }) => {
return await exchange({
using: {
fetch: async () => {
return new Response(JSON.stringify({ data: { countries: [{ name: `USA` }] } }))
// todo: if used introspection query to get schema, then default schema to that URL.
// todo: https://github.com/jasonkuhrt/graphql-request/issues/1015
const countriesClient = CountriesClient.create({ schema: `https://countries.trevorblades.com/graphql` })
.use({
name: `CustomFetch`,
anyware: async ({ exchange }) => {
return await exchange({
using: {
fetch: async () => {
return new Response(JSON.stringify({ data: { countries: [{ name: `Canada Mocked!` }] } }))
},
},
},
})
},
}).rawOrThrow
})
},
})

const { data } = await request(
gql`
{
countries {
name
}
}
`,
)
const countries = await countriesClient.query.countries({ name: true })

console.log(data)
console.log(countries)
20 changes: 5 additions & 15 deletions examples/config-http-headers.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,12 @@
/* eslint-disable */
import { CountriesClient } from './generated-clients/countries/__.js'

import { gql, Graffle } from '../src/entrypoints/alpha/main.js'

const request = Graffle.create({
const request = CountriesClient.create({
schema: `https://countries.trevorblades.com/graphql`,
headers: {
authorization: `Bearer MY_TOKEN`,
},
}).rawOrThrow
})

const { data } = await request(
gql`
{
countries {
name
}
}
`,
)
const continents = await request.query.continents({ name: true })

console.log(data)
console.log(continents)
5 changes: 5 additions & 0 deletions examples/generated-clients/countries/Client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { createPrefilled } from '../../../src/entrypoints/alpha/client.js'

import { $Index } from './SchemaRuntime.js'

export const create = createPrefilled(`countriesClient`, $Index)
14 changes: 14 additions & 0 deletions examples/generated-clients/countries/Error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
type Include<T, U> = Exclude<T, Exclude<T, U>>

type ObjectWithTypeName = { __typename: string }

const ErrorObjectsTypeNameSelectedEnum = {} as Record<string, ObjectWithTypeName>

const ErrorObjectsTypeNameSelected = Object.values(ErrorObjectsTypeNameSelectedEnum)

type ErrorObjectsTypeNameSelected = (typeof ErrorObjectsTypeNameSelected)[number]

export const isError = <$Value>(value: $Value): value is Include<$Value, ErrorObjectsTypeNameSelected> => {
return typeof value === 'object' && value !== null && '__typename' in value
&& ErrorObjectsTypeNameSelected.some(_ => _.__typename === value.__typename)
}
15 changes: 15 additions & 0 deletions examples/generated-clients/countries/Global.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { Index } from './Index.js'

declare global {
export namespace GraphQLRequestTypes {
export interface Schemas {
countriesClient: {
index: Index
customScalars: {}
featureOptions: {
schemaErrors: true
}
}
}
}
}
30 changes: 30 additions & 0 deletions examples/generated-clients/countries/Index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* eslint-disable */

import type * as Schema from './SchemaBuildtime.js'

export interface Index {
name: 'countriesClient'
Root: {
Query: Schema.Root.Query
Mutation: null
Subscription: null
}
objects: {
Continent: Schema.Object.Continent
Country: Schema.Object.Country
Language: Schema.Object.Language
State: Schema.Object.State
Subdivision: Schema.Object.Subdivision
}
unions: {}
interfaces: {}
error: {
objects: {}
objectsTypename: {}
rootResultFields: {
Query: {}
Mutation: {}
Subscription: {}
}
}
}
1 change: 1 addition & 0 deletions examples/generated-clients/countries/Scalar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from '../../../src/entrypoints/alpha/scalars.js'
154 changes: 154 additions & 0 deletions examples/generated-clients/countries/SchemaBuildtime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import type * as $ from '../../../src/entrypoints/alpha/schema.js'
import type * as $Scalar from './Scalar.ts'

// ------------------------------------------------------------ //
// Root //
// ------------------------------------------------------------ //

export namespace Root {
export type Query = $.Object$2<'Query', {
continent: $.Field<
$.Output.Nullable<Object.Continent>,
$.Args<{
code: $Scalar.ID
}>
>
continents: $.Field<
$.Output.List<Object.Continent>,
$.Args<{
filter: $.Input.Nullable<InputObject.ContinentFilterInput>
}>
>
countries: $.Field<
$.Output.List<Object.Country>,
$.Args<{
filter: $.Input.Nullable<InputObject.CountryFilterInput>
}>
>
country: $.Field<
$.Output.Nullable<Object.Country>,
$.Args<{
code: $Scalar.ID
}>
>
language: $.Field<
$.Output.Nullable<Object.Language>,
$.Args<{
code: $Scalar.ID
}>
>
languages: $.Field<
$.Output.List<Object.Language>,
$.Args<{
filter: $.Input.Nullable<InputObject.LanguageFilterInput>
}>
>
}>
}

// ------------------------------------------------------------ //
// Enum //
// ------------------------------------------------------------ //

export namespace Enum {
// -- no types --
}

// ------------------------------------------------------------ //
// InputObject //
// ------------------------------------------------------------ //

export namespace InputObject {
export type ContinentFilterInput = $.InputObject<'ContinentFilterInput', {
code: $.Input.Nullable<InputObject.StringQueryOperatorInput>
}>

export type CountryFilterInput = $.InputObject<'CountryFilterInput', {
code: $.Input.Nullable<InputObject.StringQueryOperatorInput>
continent: $.Input.Nullable<InputObject.StringQueryOperatorInput>
currency: $.Input.Nullable<InputObject.StringQueryOperatorInput>
name: $.Input.Nullable<InputObject.StringQueryOperatorInput>
}>

export type LanguageFilterInput = $.InputObject<'LanguageFilterInput', {
code: $.Input.Nullable<InputObject.StringQueryOperatorInput>
}>

export type StringQueryOperatorInput = $.InputObject<'StringQueryOperatorInput', {
eq: $.Input.Nullable<$Scalar.String>
in: $.Input.Nullable<$.Input.List<$Scalar.String>>
ne: $.Input.Nullable<$Scalar.String>
nin: $.Input.Nullable<$.Input.List<$Scalar.String>>
regex: $.Input.Nullable<$Scalar.String>
}>
}

// ------------------------------------------------------------ //
// Interface //
// ------------------------------------------------------------ //

export namespace Interface {
// -- no types --
}

// ------------------------------------------------------------ //
// Object //
// ------------------------------------------------------------ //

export namespace Object {
export type Continent = $.Object$2<'Continent', {
code: $.Field<$Scalar.ID, null>
countries: $.Field<$.Output.List<Object.Country>, null>
name: $.Field<$Scalar.String, null>
}>

export type Country = $.Object$2<'Country', {
awsRegion: $.Field<$Scalar.String, null>
capital: $.Field<$.Output.Nullable<$Scalar.String>, null>
code: $.Field<$Scalar.ID, null>
continent: $.Field<Object.Continent, null>
currencies: $.Field<$.Output.List<$Scalar.String>, null>
currency: $.Field<$.Output.Nullable<$Scalar.String>, null>
emoji: $.Field<$Scalar.String, null>
emojiU: $.Field<$Scalar.String, null>
languages: $.Field<$.Output.List<Object.Language>, null>
name: $.Field<
$Scalar.String,
$.Args<{
lang: $.Input.Nullable<$Scalar.String>
}>
>
native: $.Field<$Scalar.String, null>
phone: $.Field<$Scalar.String, null>
phones: $.Field<$.Output.List<$Scalar.String>, null>
states: $.Field<$.Output.List<Object.State>, null>
subdivisions: $.Field<$.Output.List<Object.Subdivision>, null>
}>

export type Language = $.Object$2<'Language', {
code: $.Field<$Scalar.ID, null>
name: $.Field<$Scalar.String, null>
native: $.Field<$Scalar.String, null>
rtl: $.Field<$Scalar.Boolean, null>
}>

export type State = $.Object$2<'State', {
code: $.Field<$.Output.Nullable<$Scalar.String>, null>
country: $.Field<Object.Country, null>
name: $.Field<$Scalar.String, null>
}>

export type Subdivision = $.Object$2<'Subdivision', {
code: $.Field<$Scalar.ID, null>
emoji: $.Field<$.Output.Nullable<$Scalar.String>, null>
name: $.Field<$Scalar.String, null>
}>
}

// ------------------------------------------------------------ //
// Union //
// ------------------------------------------------------------ //

export namespace Union {
// -- no types --
}
Loading

0 comments on commit 8e12e0b

Please sign in to comment.