Skip to content

Commit

Permalink
refactor: simpler decode functions
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonkuhrt committed Oct 24, 2024
1 parent 112c6d2 commit debbe39
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 40 deletions.
75 changes: 39 additions & 36 deletions src/extensions/CustomScalars/decode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,29 @@ export const decodeResultData = ({ request, data, sddm, scalars }: {
if (!sddmOutputObject) return
if (!data) return

for (const [key, value] of Object.entries(data)) {
const documentField = findDocumentField(request.operation.selectionSet, key)
const kSchema = documentField?.name.value ?? key
const sddmOutputField = sddmOutputObject.f[kSchema]
if (!sddmOutputField?.nt) continue

decodeResultValue({
parentContext: { type: `object`, object: data, key },
value,
sddmNode: sddmOutputField.nt,
documentPart: documentField?.selectionSet ?? null,
scalars,
})
}
decodeResultValue({
parentContext: null,
value: data,
sddmNode: sddmOutputObject,
documentPart: request.operation.selectionSet,
scalars,
})
}

const decodeResultValue = (input: {
parentContext: { type: `object`; object: Record<string, any>; key: string } | {
type: `list`
object: any[]
key: number
}
value: Value
parentContext:
| null
| {
type: `object`
object: Record<string, any>
fieldName: string
}
| {
type: `list`
object: any[]
index: number
}
value: Grafaid.SomeFieldData
sddmNode: SchemaDrivenDataMap.OutputNodes
documentPart: null | Grafaid.Document.SelectionSetNode
scalars: Schema.Scalar.ScalarMap
Expand All @@ -65,7 +65,7 @@ const decodeResultValue = (input: {
// todo test case of array data of scalars
value.forEach((item, index) => {
decodeResultValue({
parentContext: { type: `list`, object: value, key: index },
parentContext: { type: `list`, object: value, index },
value: item,
sddmNode,
documentPart,
Expand All @@ -79,34 +79,41 @@ const decodeResultValue = (input: {
// todo in strict mode throw error that sddmNode is inconsistent with data shape.
}
const object = value
for (const [key, value] of Object.entries(object)) {
const documentField = findDocumentField(documentPart, key)
const kSchema = documentField?.name.value ?? key
for (const [fieldName, value] of Object.entries(object)) {
// TODO optimize field lookup
// We need a smart algorithm that considers:
// key space of schema vs key space of data
const documentField = findDocumentField(documentPart, fieldName)
const kSchema = documentField?.name.value ?? fieldName
const sddmOutputField = sddmNode.f[kSchema]
if (!sddmOutputField?.nt) continue
decodeResultValue({
parentContext: { type: `object`, object, key },
parentContext: { type: `object`, object, fieldName },
value,
sddmNode: sddmOutputField.nt,
documentPart: documentField?.selectionSet ?? null,
scalars,
})
}
} else {
if (!parentContext) {
// Should be impossible. Strict mode could error here.
return
}
if (SchemaDrivenDataMap.isScalar(sddmNode)) {
const decodedValue = Schema.Scalar.applyCodec(sddmNode.codec.decode, value)
if (parentContext.type === `object`) {
parentContext.object[parentContext.key] = decodedValue
parentContext.object[parentContext.fieldName] = decodedValue
} else {
parentContext.object[parentContext.key] = decodedValue
parentContext.object[parentContext.index] = decodedValue
}
} else if (SchemaDrivenDataMap.isCustomScalarName(sddmNode)) {
const scalar = Schema.Scalar.lookupCustomScalarOrFallbackToString(scalars, sddmNode)
const decodedValue = Schema.Scalar.applyCodec(scalar.codec.decode, value)
if (parentContext.type === `object`) {
parentContext.object[parentContext.key] = decodedValue
parentContext.object[parentContext.fieldName] = decodedValue
} else {
parentContext.object[parentContext.key] = decodedValue
parentContext.object[parentContext.index] = decodedValue
}
} else {
// enums not decoded.
Expand All @@ -116,23 +123,19 @@ const decodeResultValue = (input: {

const findDocumentField = (
selectionSet: null | Grafaid.Document.SelectionSetNode,
k: string,
fieldName: string,
): Grafaid.Document.FieldNode | null => {
if (!selectionSet) return null

for (const selection of selectionSet.selections) {
if (selection.kind === Kind.FIELD && (selection.alias?.value ?? selection.name.value) === k) {
if (selection.kind === Kind.FIELD && (selection.alias?.value ?? selection.name.value) === fieldName) {
return selection
}
if (selection.kind === Kind.INLINE_FRAGMENT) {
const result = findDocumentField(selection.selectionSet, k)
const result = findDocumentField(selection.selectionSet, fieldName)
if (result !== null) return result
}
}

return null
}

type Value = Grafaid.Schema.StandardScalarRuntimeTypes[] | Grafaid.Schema.StandardScalarRuntimeTypes | null | {
[k: string]: Value
}
13 changes: 11 additions & 2 deletions src/lib/grafaid/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,17 @@ export type Variables = {
[key: string]: string | boolean | null | number | Variables
}

export type SomeObjectData = Record<string, any>
export type SomeFieldData = SomeObjectData | Grafaid.Schema.StandardScalarRuntimeTypes
export type SomeObjectData = {
[fieldName: string]: any // SomeFieldData <-- If we put this here tsc has crashes with OOM.
}

export type SomeFieldData =
| null
| Grafaid.Schema.StandardScalarRuntimeTypes
| Grafaid.Schema.StandardScalarRuntimeTypes[]
| {
[fieldName: string]: SomeFieldData
}

export type GraphQLExecutionResultError = Errors.ContextualAggregateError<GraphQLError>

Expand Down
4 changes: 2 additions & 2 deletions website/content/guides/20_getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: Getting Started

# Getting Started

This short guide will shepherd you through an example beginning from basic usage an then demonstrating use of the optional document builder. Node is used but Deno and Bun users should be able to follow along as well.
This short guide will take you from basic usage to use of the optional document builder. Node is used but Deno and Bun users should be able to follow along as well.

## 🏡 Setup Your Project

Expand All @@ -24,7 +24,7 @@ pnpm add --development typescript tsx @tsconfig/strictest
```

```sh
touch tsconfig.json
touch tsconfig.json main.ts
```

```json tsconfig.json
Expand Down

0 comments on commit debbe39

Please sign in to comment.