Skip to content

Commit

Permalink
refactor: document data type flow (#1130)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonkuhrt authored Sep 26, 2024
1 parent 5555c20 commit 61ecd39
Show file tree
Hide file tree
Showing 56 changed files with 708 additions and 603 deletions.
2 changes: 1 addition & 1 deletion examples/$/show.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const show = <$Logger extends Logger = typeof console.log>(
subTitle?: string,
): ReturnType<$Logger> => {
const write = console.log
const inspected = inspect(value, { depth: null, colors: true })
const inspected = typeof value === 'string' ? value : inspect(value, { depth: null, colors: true })
const message = renderShow(inspected, subTitle)
return write(message) as ReturnType<$Logger>
}
Expand Down
3 changes: 2 additions & 1 deletion examples/55_generated/generated_arguments__arguments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import { showJson } from '../$/helpers.js'

const atlas = Pokemon.create()

// dprint-ignore
const pokemons = await atlas.query.pokemons({
$: { filter: { name: { in: [`Pikachu`, `Charizard`] } } },
$: { filter: { name: { in: [`Pikachu`, `Charizard`] } } }, // [!code highlight]
name: true,
trainer: { name: true },
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---------------------------------------- SHOW ----------------------------------------
'This operation was aborted'
This operation was aborted
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
headers: Headers {
accept: 'application/graphql-response+json; charset=utf-8, application/json; charset=utf-8',
'content-type': 'application/json',
'x-sent-at-time': '1727319638284'
'x-sent-at-time': '1727365576054'
},
signal: undefined,
method: 'post',
Expand Down
2 changes: 1 addition & 1 deletion examples/__outputs__/20_output/output_envelope.output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
headers: Headers {
'content-type': 'application/graphql-response+json; charset=utf-8',
'content-length': '104',
date: 'Thu, 26 Sep 2024 03:00:38 GMT',
date: 'Thu, 26 Sep 2024 15:46:16 GMT',
connection: 'keep-alive',
'keep-alive': 'timeout=5'
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
at runPipeline (/some/path/to/runPipeline.ts:XX:XX:18)
at async Object.run (/some/path/to/main.ts:XX:XX:22)
at async run (/some/path/to/client.ts:XX:XX:20)
at async executeRootType (/some/path/to/client.ts:XX:XX:12)
at async executeDocument (/some/path/to/client.ts:XX:XX:12)
at async executeRootTypeField (/some/path/to/client.ts:XX:XX:20)
at async <anonymous> (/some/path/to/output_envelope_envelope-error__envelope-error.ts:XX:XX:16) {
context: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ ContextualError: There was an error in the extension "anonymous" (use named func
at runPipeline (/some/path/to/runPipeline.ts:XX:XX:18)
at async Object.run (/some/path/to/main.ts:XX:XX:22)
at async run (/some/path/to/client.ts:XX:XX:20)
at async executeRootType (/some/path/to/client.ts:XX:XX:12)
at async executeDocument (/some/path/to/client.ts:XX:XX:12)
at async executeRootTypeField (/some/path/to/client.ts:XX:XX:20)
at async <anonymous> (/some/path/to/output_envelope_envelope_error-throw__envelope-error-throw.ts:XX:XX:1) {
context: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ ContextualError: There was an error in the extension "anonymous" (use named func
at runPipeline (/some/path/to/runPipeline.ts:XX:XX:18)
at async Object.run (/some/path/to/main.ts:XX:XX:22)
at async run (/some/path/to/client.ts:XX:XX:20)
at async executeRootType (/some/path/to/client.ts:XX:XX:12)
at async executeDocument (/some/path/to/client.ts:XX:XX:12)
at async executeRootTypeField (/some/path/to/client.ts:XX:XX:20)
at async <anonymous> (/some/path/to/output_return-error.ts:XX:XX:18) {
context: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ ContextualAggregateError: One or more errors in the execution result.
at handleOutput (/some/path/to/handleOutput.ts:XX:XX:19)
at run (/some/path/to/client.ts:XX:XX:12)
at process.processTicksAndRejections (node:internal/process/task_queues:XX:XX)
at async executeRootType (/some/path/to/client.ts:XX:XX:12)
at async executeDocument (/some/path/to/client.ts:XX:XX:12)
at async executeRootTypeField (/some/path/to/client.ts:XX:XX:20)
at async <anonymous> (/some/path/to/output_return-error_return-error-execution__return-error-execution.ts:XX:XX:16) {
context: {},
Expand Down Expand Up @@ -40,7 +40,7 @@ ContextualError: There was an error in the extension "anonymous" (use named func
at process.processTicksAndRejections (node:internal/process/task_queues:XX:XX)
at async Object.run (/some/path/to/main.ts:XX:XX:22)
at async run (/some/path/to/client.ts:XX:XX:20)
at async executeRootType (/some/path/to/client.ts:XX:XX:12)
at async executeDocument (/some/path/to/client.ts:XX:XX:12)
at async executeRootTypeField (/some/path/to/client.ts:XX:XX:20)
at async <anonymous> (/some/path/to/output_return-error_return-error-execution__return-error-execution.ts:XX:XX:3) {
context: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
}
},
instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined },
traceId: '851f3f771b76e4969a2f8c084f85759d',
parentId: 'ebd5237ad56b820c',
traceId: '99a1b00f220469bd559f6fdc09b75cfc',
parentId: 'fb04e4436519eebf',
traceState: undefined,
name: 'encode',
id: 'ff492c55cf5462ff',
id: 'b9cc31cb6dcef7bb',
kind: 0,
timestamp: 1727319638868000,
duration: 1170.584,
timestamp: 1727365576823000,
duration: 586.292,
attributes: {},
status: { code: 0 },
events: [],
Expand All @@ -33,14 +33,14 @@
}
},
instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined },
traceId: '851f3f771b76e4969a2f8c084f85759d',
parentId: 'ebd5237ad56b820c',
traceId: '99a1b00f220469bd559f6fdc09b75cfc',
parentId: 'fb04e4436519eebf',
traceState: undefined,
name: 'pack',
id: '9174a3424a228e28',
id: 'fb77c65e19244b1f',
kind: 0,
timestamp: 1727319638871000,
duration: 36417.291,
timestamp: 1727365576831000,
duration: 19896.75,
attributes: {},
status: { code: 0 },
events: [],
Expand All @@ -57,14 +57,14 @@
}
},
instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined },
traceId: '851f3f771b76e4969a2f8c084f85759d',
parentId: 'ebd5237ad56b820c',
traceId: '99a1b00f220469bd559f6fdc09b75cfc',
parentId: 'fb04e4436519eebf',
traceState: undefined,
name: 'exchange',
id: '85de30bd471a1d11',
id: '7e3a75386432d606',
kind: 0,
timestamp: 1727319638909000,
duration: 24460.084,
timestamp: 1727365576852000,
duration: 29439.625,
attributes: {},
status: { code: 0 },
events: [],
Expand All @@ -81,14 +81,14 @@
}
},
instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined },
traceId: '851f3f771b76e4969a2f8c084f85759d',
parentId: 'ebd5237ad56b820c',
traceId: '99a1b00f220469bd559f6fdc09b75cfc',
parentId: 'fb04e4436519eebf',
traceState: undefined,
name: 'unpack',
id: '81208c873ce84df5',
id: '6263aef06e4164d0',
kind: 0,
timestamp: 1727319638933000,
duration: 1301.541,
timestamp: 1727365576881000,
duration: 1157,
attributes: {},
status: { code: 0 },
events: [],
Expand All @@ -105,14 +105,14 @@
}
},
instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined },
traceId: '851f3f771b76e4969a2f8c084f85759d',
parentId: 'ebd5237ad56b820c',
traceId: '99a1b00f220469bd559f6fdc09b75cfc',
parentId: 'fb04e4436519eebf',
traceState: undefined,
name: 'decode',
id: '0e084f67d12e45c7',
id: 'f6e875f59111e613',
kind: 0,
timestamp: 1727319638935000,
duration: 199.208,
timestamp: 1727365576883000,
duration: 193.042,
attributes: {},
status: { code: 0 },
events: [],
Expand All @@ -129,14 +129,14 @@
}
},
instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined },
traceId: '851f3f771b76e4969a2f8c084f85759d',
traceId: '99a1b00f220469bd559f6fdc09b75cfc',
parentId: undefined,
traceState: undefined,
name: 'request',
id: 'ebd5237ad56b820c',
id: 'fb04e4436519eebf',
kind: 0,
timestamp: 1727319638867000,
duration: 68430.791,
timestamp: 1727365576822000,
duration: 61277.208,
attributes: {},
status: { code: 0 },
events: [],
Expand Down
1 change: 1 addition & 0 deletions src/entrypoints/_Print.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { print as document } from '../layers/4_document/print.js'
1 change: 1 addition & 0 deletions src/entrypoints/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export { type WithInput } from '../layers/6_client/Settings/inputIncrementable/i
export * from '../lib/prelude.js'
export * from './__Graffle.js'
export * as Preset from './_Preset.js'
export * as Print from './_Print.js'
4 changes: 2 additions & 2 deletions src/layers/2_SelectionSet/print.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { $Index as schemaIndex } from '../../../tests/_/schema/generated/modules
import type * as SelectionSets from '../../../tests/_/schema/generated/modules/SelectionSets.js'
import { outputConfigDefault } from '../6_client/Settings/Config.js'
import type { Context } from './print.js'
import { resolveRootType } from './print.js'
import { rootType } from './print.js'

// eslint-disable-next-line
// @ts-ignore
Expand All @@ -30,7 +30,7 @@ const testEachArgs = [
initialInput: {} as any,
},
}
const graphqlDocumentString = resolveRootType(context, schemaIndex[`Root`][`Query`], ss as any)
const graphqlDocumentString = rootType(context, schemaIndex[`Root`][`Query`], ss as any)
// Should parse, ensures is syntactically valid graphql document.
const document = parse(graphqlDocumentString)
const graphqlDocumentStringFormatted = print(document)
Expand Down
69 changes: 23 additions & 46 deletions src/layers/2_SelectionSet/print.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,95 +3,72 @@ import { assertArray, assertObject, entriesStrict, lowerCaseFirstLetter } from '
import { Schema } from '../1_Schema/__.js'
import { readMaybeThunk } from '../1_Schema/core/helpers.js'
import type { Config } from '../6_client/Settings/Config.js'
import type { Indicator } from './_indicator.js'
import { Directive } from './Directive/__.js'
import { isSelectFieldName } from './helpers.js'
import type { Indicator } from './indicator.js'
// import type { Indicator } from './indicator.js'
import { isIndicator, isPositiveIndicator } from './indicator.js'
import { parseClientOn, toGraphQLOn } from './on.js'
import { parseClientFieldItem } from './runtime/FieldItem.js'
import { createFieldName } from './runtime/FieldName.js'
import { normalizeAlias } from './types.js'
import { type ArgValue, normalizeAlias, type ObjectLike, type SS } from './types.js'

interface SpecialFields extends Directive.$Fields {
// todo - this requires having the schema at runtime to know which fields to select.
// $scalars?: SelectionSet.Indicator
$?: Args
}

type Args = { [k: string]: ArgValue }

type ArgValue = string | boolean | null | number | Args

export type DocumentObject = {
query?: Record<string, GraphQLObjectSelection>
mutation?: Record<string, GraphQLObjectSelection>
}

export type GraphQLRootSelection = { query: GraphQLObjectSelection } | { mutation: GraphQLObjectSelection }

// todo duplicaets the ObjectLike type in other module
export type GraphQLObjectSelection = Record<string, Indicator | SS>

export type SS = {
[k: string]: Indicator | SS
} & SpecialFields

type FieldValue = SS | Indicator
type FieldValue = SS | Indicator.Indicator

export interface Context {
schemaIndex: Schema.Index
config: Config
}

export const resolveRootType = (
export const rootType = (
context: Context,
rootObjectDef: Schema.Output.RootType,
selectionSet: GraphQLObjectSelection,
selectionSet: ObjectLike,
operationName: string = ``,
) => {
const operationTypeName = lowerCaseFirstLetter(rootObjectDef.fields.__typename.type.type)
return `${operationTypeName} ${operationName} { ${resolveObjectLikeField(context, rootObjectDef, selectionSet)} }`
}

const resolveArgValue = (
const argValue = (
context: Context,
schemaArgTypeMaybeThunk: Schema.Input.Any,
argValue: ArgValue,
value: ArgValue,
): string => {
if (argValue === null) return String(null) // todo could check if index agrees is nullable.
if (value === null) return String(null) // todo could check if index agrees is nullable.

const schemaArgType = readMaybeThunk(schemaArgTypeMaybeThunk)

switch (schemaArgType.kind) {
case `nullable`:
return resolveArgValue(context, schemaArgType.type, argValue)
return argValue(context, schemaArgType.type, value)
case `list`: {
assertArray(argValue)
const value = argValue.map(_ => resolveArgValue(context, schemaArgType.type, _ as ArgValue))
return `[${value.join(`, `)}]`
assertArray(value)
const values = value.map(_ => argValue(context, schemaArgType.type, _ as ArgValue))
return `[${values.join(`, `)}]`
}
case `InputObject`: {
assertObject(argValue)
const entries = Object.entries(argValue).map(([argName, argValue]) => {
const schemaArgField = schemaArgType.fields[argName] as Schema.Input.Field | undefined
if (!schemaArgField) throw new Error(`Arg not found: ${argName}`)
return [argName, resolveArgValue(context, schemaArgField.type, argValue)]
assertObject(value)
const entries = Object.entries(value).map(([argName_, argValue_]) => {
const schemaArgField = schemaArgType.fields[argName_] as Schema.Input.Field | undefined
if (!schemaArgField) throw new Error(`Arg not found: ${argName_}`)
return [argName_, argValue(context, schemaArgField.type, argValue_)]
})
return `{ ${entries.map(([k, v]) => `${k!}: ${v!}`).join(`, `)} }`
}
case `Enum`: {
return String(argValue)
return String(value)
}
case `Scalar`: {
// @ts-expect-error fixme
return JSON.stringify(schemaArgType.codec.encode(argValue))
return JSON.stringify(schemaArgType.codec.encode(value))
}
default:
throw new Error(`Unsupported arg kind: ${JSON.stringify(schemaArgType)}`)
}
}

const resolveArgs = (context: Context, schemaField: Schema.SomeField, ss: Indicator | SS) => {
const resolveArgs = (context: Context, schemaField: Schema.SomeField, ss: Indicator.Indicator | SS) => {
if (isIndicator(ss)) return ``

const { $ } = ss
Expand All @@ -107,7 +84,7 @@ const resolveArgs = (context: Context, schemaField: Schema.SomeField, ss: Indica
argEntries.map(([argFieldName, v]) => {
const schemaArgField = schemaArgs.fields[argFieldName] as Schema.Input.Field | undefined
if (!schemaArgField) throw new Error(`Arg field ${argFieldName} not found in schema.`)
const valueEncoded = resolveArgValue(context, schemaArgField.type, v)
const valueEncoded = argValue(context, schemaArgField.type, v)
return `${argFieldName}: ${valueEncoded}`
}).join(`, `)
})`
Expand Down Expand Up @@ -137,7 +114,7 @@ const resolveFieldValue = (
return `${args} ${directives}`
}

const selection = Object.fromEntries(selects) as GraphQLObjectSelection
const selection = Object.fromEntries(selects) as ObjectLike

// eslint-disable-next-line
// @ts-ignore ID error
Expand Down
18 changes: 16 additions & 2 deletions src/layers/2_SelectionSet/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,24 @@ import type { OmitNullableFields, PickNullableFields, Schema } from '../1_Schema
import type { Indicator } from './_indicator.js'
import type { Directive } from './Directive/__.js'

export type ObjectLike = {
[fieldName: string]: Any
export type ArgValue = string | boolean | null | number | Args_

export type Args_ = { [k: string]: ArgValue }

interface SpecialFields extends Directive.$Fields {
// todo - this requires having the schema at runtime to know which fields to select.
// $scalars?: SelectionSet.Indicator
$?: Args_
}

export type SS = {
[k: string]: Indicator.Indicator | SS
} & SpecialFields

export type ObjectLike = Record<string, Indicator.Indicator | SS>

export type GraphQLRootSelection = { query: ObjectLike } | { mutation: ObjectLike }

export type Any = AnyExceptAlias | AliasInput

export type AnyExceptAlias = ObjectLike | Indicator.Any
Expand Down
Loading

0 comments on commit 61ecd39

Please sign in to comment.