Skip to content

Commit

Permalink
feat: expose generated select sets (#1172)
Browse files Browse the repository at this point in the history
This change exposes the generated selection sets under "SelectionSets"
namespace on the root generated namespace. E.g. `Graffle.SelectionSets`
now works.
  • Loading branch information
jasonkuhrt authored Oct 7, 2024
1 parent d63c6a8 commit 597eb6b
Show file tree
Hide file tree
Showing 18 changed files with 642 additions and 58 deletions.
12 changes: 0 additions & 12 deletions src/layers/2_Select/Indicator/indicator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,6 @@ export type NoArgsIndicator = Indicator | Directive.$Fields

export type NoArgsIndicator$Expanded = UnionExpanded<Indicator | Simplify<Directive.$Fields>>

// // dprint-ignore
// type ArgsIndicator<$Args extends Schema.Args<any>> =
// $Args['isFieldsAllNullable'] extends true
// ? ({ $?: Args<$Args> } & Directive.$Fields) | Indicator
// : { $: Args<$Args> } & Directive.$Fields

// // dprint-ignore
// export type IndicatorForField<$Field extends SomeField> =
// $Field['args'] extends null
// ? NoArgsIndicator
// : ArgsIndicator<ExcludeNull<$Field['args']>>

export const isPositiveLikeFieldValue = (v: any): v is Positive => {
return !isNegativeIndicator(v)
}
7 changes: 5 additions & 2 deletions src/layers/2_Select/Indicator/negative.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import type { UnionExpanded, Values } from '../../../lib/prelude.js'
import type { UnionExpanded } from '../../../lib/prelude.js'

export const negativeIndicatorEnum = {
false: false,
undefined: undefined,
} as const

export type Negative = UnionExpanded<Values<typeof negativeIndicatorEnum>>
// We do not definite the type in a DRY way like below because it causes
// IDEs to show Values<...> in the final type making it harder to read.
// export type Negative = UnionExpanded<Values<typeof negativeIndicatorEnum>>
export type Negative = UnionExpanded<false | undefined>

export const isNegativeIndicator = (v: any): v is Negative => {
return v === negativeIndicatorEnum.false || v === negativeIndicatorEnum.undefined
Expand Down
1 change: 1 addition & 0 deletions src/layers/4_generator/__snapshots__/generate.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import './modules/Global.js'
export { create } from './modules/Client.js'
export { isError } from './modules/Error.js'
export { Select } from './modules/Select.js'
export * as SelectionSets from './modules/SelectionSets.js'
"
`;

Expand Down
36 changes: 28 additions & 8 deletions src/layers/4_generator/generators/SelectionSets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,12 @@ const renderObject = createCodeGenerator<{ node: GraphQLObjectType }>(
const doc = Code.TSDoc(`
Select the \`${field.name}\` field on the \`${node.name}\` object. Its type is ${type}.
`)
const propertyRendered = Helpers.outputFieldAlisable(field.name, `${renderName(node)}.${renderName(field)}`)
const propertyRendered = Helpers.outputFieldAlisable(
field.name,
`${renderName(node)}.${renderName(field)}`,
true,
analyzeArgsNullability(field.args).isAllNullable,
)
return doc + `\n` + propertyRendered
}).join(`\n`)

Expand Down Expand Up @@ -295,8 +300,8 @@ const renderField = createCodeGenerator<{ field: GraphQLField<any, any> }>(
)
code()
code(
Helpers.type(
`${nameRendered}$Expanded`,
Helpers.typeExpanded(
nameRendered,
`$Utilities.UnionExpanded<$Select.Indicator.Indicator | ${nameRendered}$SelectionSet>`,
),
)
Expand All @@ -306,14 +311,13 @@ const renderField = createCodeGenerator<{ field: GraphQLField<any, any> }>(
)
code()
} else {
// 1+ arguments required.
// todo test that a directive can be passed with the intersection that otherwise cannot be.
code(Helpers.$interface(nameRendered, `$Select.Bases.Base`, argsRendered))
code()
code(Helpers.type(`${nameRendered}$Expanded`, nameRendered))
code()
}
} else {
code(Helpers.type(`${nameRendered}$Expanded`, `$Select.Indicator.NoArgsIndicator$Expanded`))
code(Helpers.typeExpanded(nameRendered, `$Select.Indicator.NoArgsIndicator$Expanded`))
code()
code(Helpers.type(nameRendered, `$Select.Indicator.NoArgsIndicator`))
code()
Expand Down Expand Up @@ -402,6 +406,17 @@ namespace Helpers {
export const $interface = (name: string, extendsClause: string | null, fields: string) => {
return `export interface ${name} ${extendsClause ? ` extends ${extendsClause}` : ``} { ${fields} }`
}
export const typeExpanded = (name: string, type: string) => {
const jsdoc = Code.TSDoc(`
This is the "expanded" version of the \`${name}\` type. It is identical except for the fact
that IDEs will display its contents (a union type) directly, rather than the name of this type.
In some cases, this is a preferable DX, making the types easier to read for users.
`)
return `
${jsdoc}
export type ${name}$Expanded = ${type}
`
}
export const type = (name: string, type: string) => {
return `export type ${name} = ${type}`
}
Expand All @@ -410,9 +425,14 @@ namespace Helpers {
return `${name}?: ${type}`
}

export const outputFieldAlisable = (name: string, type: string, aliasable: boolean = true) => {
export const outputFieldAlisable = (
name: string,
type: string,
aliasable: boolean = true,
isHasExpanded: boolean = true,
) => {
const alias = aliasable ? `| $Select.SelectAlias.SelectAlias<${type}>` : ``
return `${name}?: ${type}$Expanded${alias}`
return `${name}?: ${type}${isHasExpanded ? `$Expanded` : ``}${alias}`
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/layers/4_generator/generators/_.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { createModuleGenerator } from '../helpers/moduleGenerator.js'
import { ModuleGeneratorClient } from './Client.js'
import { ModuleGeneratorError } from './Error.js'
import { ModuleGeneratorSelect } from './Select.js'
import { ModuleGeneratorSelectionSets } from './SelectionSets.js'

export const ModuleGenerator_ = createModuleGenerator(
`_`,
Expand All @@ -16,6 +17,7 @@ export const ModuleGenerator_ = createModuleGenerator(
`export { Select } from './modules/${ModuleGeneratorSelect.name}.js'`,
`export { isError } from './modules/${ModuleGeneratorError.name}.js'`,
`export { create } from './modules/${ModuleGeneratorClient.name}.js'`,
`export * as SelectionSets from './modules/${ModuleGeneratorSelectionSets.name}.js'`,
)

return code
Expand Down
4 changes: 2 additions & 2 deletions src/layers/6_client/client.customScalar.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { describe, expect } from 'vitest'
import { createResponse, test } from '../../../tests/_/helpers.js'
import { db } from '../../../tests/_/schemas/db.js'
import type { Query } from '../../../tests/_/schemas/kitchen-sink/graffle/modules/SelectionSets.js'
import type { Graffle } from '../../../tests/_/schemas/kitchen-sink/graffle/__.js'

const date0Encoded = db.date0.toISOString()

type TestCase = [
describe: string,
query: Query,
query: Graffle.SelectionSets.Query,
responseData: object,
expectedData: object,
]
Expand Down
1 change: 1 addition & 0 deletions tests/_/schemas/kitchen-sink/graffle/_.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ import './modules/Global.js'
export { create } from './modules/Client.js'
export { isError } from './modules/Error.js'
export { Select } from './modules/Select.js'
export * as SelectionSets from './modules/SelectionSets.js'
Loading

0 comments on commit 597eb6b

Please sign in to comment.