Skip to content

Commit

Permalink
save
Browse files Browse the repository at this point in the history
  • Loading branch information
belopash committed Jul 8, 2024
1 parent 71ca067 commit 3af413e
Show file tree
Hide file tree
Showing 13 changed files with 1,201 additions and 896 deletions.
44 changes: 1 addition & 43 deletions graphql/openreader/src/dialect/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {OrderBy, Where} from '../ir/args'
import assert from 'assert'

export enum Dialect {
OpenCRUD = 'opencrud',
OpenCrud = 'opencrud',
TheGraph = 'thegraph',
}

Expand Down Expand Up @@ -47,45 +47,3 @@ export function toCondition(op: 'AND' | 'OR', operands: Where[]): Where | undefi
return {op, args: operands}
}
}


export function parseWhereKey(key: string): {op: Where['op'], field: string} {
let m = WHERE_KEY_REGEX.exec(key)
if (m) {
return {op: m[2] as Where['op'], field: m[1]}
} else {
return {op: 'REF', field: key}
}
}


const WHERE_KEY_REGEX = (() => {
let ops: Where['op'][] = [
"eq",
"not_eq",
"gt",
"gte",
"lt",
"lte",
"contains",
"not_contains",
"containsInsensitive",
"not_containsInsensitive",
"startsWith",
"not_startsWith",
"endsWith",
"not_endsWith",
"containsAll",
"containsAny",
"containsNone",
"jsonContains",
"jsonHasKey",
"isNull",
"some",
"every",
"none",
"in",
"not_in",
]
return new RegExp(`^([^_]*)_(${ops.join('|')})$`)
})()
2 changes: 1 addition & 1 deletion graphql/openreader/src/dialect/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export * from './common'
export function getSchemaBuilder(options: SchemaOptions & {dialect?: Dialect}): SchemaBuilder {
switch (options.dialect) {
case undefined:
case Dialect.OpenCRUD:
case Dialect.OpenCrud:
return new (require('./opencrud/schema').SchemaBuilder)(options)
case Dialect.TheGraph:
return new (require('./thegraph/schema').SchemaBuilder)(options)
Expand Down
43 changes: 42 additions & 1 deletion graphql/openreader/src/dialect/opencrud/where.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {unexpectedCase} from "@subsquid/util-internal"
import assert from "assert"
import {Where} from "../../ir/args"
import {ensureArray} from "../../util/util"
import {parseWhereKey, toCondition} from '../common'
import {toCondition} from '../common'


export function parseWhere(whereArg?: any): Where | undefined {
Expand Down Expand Up @@ -86,3 +86,44 @@ export function parseWhere(whereArg?: any): Where | undefined {
return conjunction
}
}

export function parseWhereKey(key: string): {op: Where['op'], field: string} {
let m = WHERE_KEY_REGEX.exec(key)
if (m) {
return {op: m[2] as Where['op'], field: m[1]}
} else {
return {op: 'REF', field: key}
}
}


const WHERE_KEY_REGEX = (() => {
let ops: Where['op'][] = [
"eq",
"not_eq",
"gt",
"gte",
"lt",
"lte",
"contains",
"not_contains",
"containsInsensitive",
"not_containsInsensitive",
"startsWith",
"not_startsWith",
"endsWith",
"not_endsWith",
"containsAll",
"containsAny",
"containsNone",
"jsonContains",
"jsonHasKey",
"isNull",
"some",
"every",
"none",
"in",
"not_in",
]
return new RegExp(`^([^_]*)_(${ops.join('|')})$`)
})()
36 changes: 15 additions & 21 deletions graphql/openreader/src/dialect/thegraph/orderBy.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,25 @@
import assert from "assert"
import type { Model } from "../../model"
import { getUniversalProperties } from '../../model.tools'
import { OrderBy, SortOrder } from "../../ir/args"
import assert from 'assert'
import type {Model} from '../../model'
import {getUniversalProperties} from '../../model.tools'
import {OrderBy, SortOrder} from '../../ir/args'
import {mergeOrderBy} from '../common'


export type TheGraphOrderByValue = string


export type TheGraph_OrderBy_List = ReadonlySet<TheGraphOrderByValue>


const MAPPING_CACHE = new WeakMap<Model, Record<string, TheGraph_OrderBy_List>>()


export function getOrderByList(model: Model, typeName: string): TheGraph_OrderBy_List {
let cache = MAPPING_CACHE.get(model)
if (cache == null) {
cache = {}
MAPPING_CACHE.set(model, cache)
}
if (cache[typeName]) return cache[typeName]
return cache[typeName] = buildOrderByList(model, typeName, 2)
return (cache[typeName] = buildOrderByList(model, typeName, 2))
}


function buildOrderByList(model: Model, typeName: string, depth: number): TheGraph_OrderBy_List {
if (depth <= 0) return new Set()
let properties = getUniversalProperties(model, typeName)
Expand All @@ -40,22 +35,19 @@ function buildOrderByList(model: Model, typeName: string, depth: number): TheGra
break
case 'object':
case 'union':
for (let [name, spec] of buildOrderByList(model, propType.name, depth - 1)) {
for (let name of buildOrderByList(model, propType.name, depth - 1)) {
m.add(key + '__' + name)
}
break
case 'fk':
case 'lookup':
m.add(key)
for (let [name, spec] of buildOrderByList(model, propType.entity, depth - 1)) {
for (let name of buildOrderByList(model, propType.entity, depth - 1)) {
m.add(key + '__' + name)
}
break
}
}
if (model[typeName].kind == 'interface') {
m.add('__type')
}
return m
}

Expand All @@ -68,14 +60,16 @@ export const ORDER_DIRECTIONS: Record<string, SortOrder> = {
desc_nulls_last: 'DESC NULLS LAST',
}

export function parseOrderBy(model: Model, typeName: string, input: {orderBy: string, direction?: string}): OrderBy {
export function parseOrderBy(model: Model, typeName: string, input: {orderBy: string; direction?: string}): OrderBy {
let list = getOrderByList(model, typeName)
assert(list.has(input.orderBy))

const sortOrder = input.orderBy ? ORDER_DIRECTIONS[input.orderBy] : ORDER_DIRECTIONS['asc']
const sortOrder = input.direction ? ORDER_DIRECTIONS[input.direction] : ORDER_DIRECTIONS['asc']
assert(sortOrder)

return {
[input.orderBy]: sortOrder
}
}
const keys = input.orderBy.split('__').reverse()
const res = keys.reduce((res: OrderBy | null, key) => ({[key]: res ?? sortOrder}), null)
assert(res)

return res
}
54 changes: 22 additions & 32 deletions graphql/openreader/src/dialect/thegraph/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {Model} from '../../model'
import {getQueryableEntities} from '../../model.tools'
import {simplifyResolveTree} from '../../util/resolve-tree'
import {parseWhere} from './where'

import {parseOrderBy} from './orderBy'

export function parseObjectTree(
model: Model,
Expand All @@ -19,16 +19,16 @@ export function parseObjectTree(
let requests: FieldRequest[] = []
let requestedScalars: Record<string, true> = {}
let object = model[typeName]
assert(object.kind == "entity" || object.kind == "object")
assert(object.kind == 'entity' || object.kind == 'object')

let fields = simplifyResolveTree(schema, tree, typeName).fields
for (let alias in fields) {
let f = fields[alias]
let prop = object.properties[f.name]
switch(prop.type.kind) {
case "scalar":
case "enum":
case "list":
switch (prop.type.kind) {
case 'scalar':
case 'enum':
case 'list':
if (requestedScalars[f.name] == null) {
requestedScalars[f.name] = true
requests.push({
Expand All @@ -37,24 +37,24 @@ export function parseObjectTree(
kind: prop.type.kind,
type: prop.type,
prop,
index: 0
index: 0,
} as OpaqueRequest)
}
break
case "object":
case 'object':
requests.push({
field: f.name,
aliases: [f.alias],
kind: prop.type.kind,
type: prop.type,
prop,
index: 0,
children: parseObjectTree(model, prop.type.name, schema, f)
children: parseObjectTree(model, prop.type.name, schema, f),
})
break
case "union": {
case 'union': {
let union = model[prop.type.name]
assert(union.kind == "union")
assert(union.kind == 'union')
let children: FieldRequest[] = []
for (let variant of union.variants) {
for (let req of parseObjectTree(model, variant, schema, f)) {
Expand All @@ -69,33 +69,33 @@ export function parseObjectTree(
type: prop.type,
prop,
index: 0,
children
children,
})
break
}
case "fk":
case 'fk':
requests.push({
field: f.name,
aliases: [f.alias],
kind: prop.type.kind,
type: prop.type,
prop,
index: 0,
children: parseObjectTree(model, prop.type.entity, schema, f)
children: parseObjectTree(model, prop.type.entity, schema, f),
})
break
case "lookup":
case 'lookup':
requests.push({
field: f.name,
aliases: [f.alias],
kind: prop.type.kind,
type: prop.type,
prop,
index: 0,
children: parseObjectTree(model, prop.type.entity, schema, f)
children: parseObjectTree(model, prop.type.entity, schema, f),
})
break
case "list-lookup":
case 'list-lookup':
requests.push({
field: f.name,
aliases: [f.alias],
Expand All @@ -104,7 +104,7 @@ export function parseObjectTree(
prop,
index: 0,
args: parseSqlArguments(model, prop.type.entity, f.args),
children: parseObjectTree(model, prop.type.entity, schema, f)
children: parseObjectTree(model, prop.type.entity, schema, f),
})
break
default:
Expand All @@ -115,7 +115,6 @@ export function parseObjectTree(
return requests
}


export function parseSqlArguments(model: Model, typeName: string, gqlArgs: any): SqlArguments {
let args: SqlArguments = {}

Expand All @@ -125,25 +124,22 @@ export function parseSqlArguments(model: Model, typeName: string, gqlArgs: any):
}

if (gqlArgs.orderBy) {
args.orderBy = {
[gqlArgs.orderBy]: gqlArgs.orderDirection === 'asc' ? 'ASC' : 'DESC'
}
args.orderBy = parseOrderBy(model, typeName, {orderBy: gqlArgs.orderBy, direction: gqlArgs.orderDirection})
}

if (gqlArgs.skip) {
assert(typeof gqlArgs.skip == "number")
assert(typeof gqlArgs.skip == 'number')
args.offset = gqlArgs.skip
}

if (gqlArgs.first != null) {
assert(typeof gqlArgs.first == "number")
assert(typeof gqlArgs.first == 'number')
args.limit = gqlArgs.first
}

return args
}


export function parseQueryableTree(
model: Model,
queryableName: string,
Expand All @@ -157,13 +153,7 @@ export function parseQueryableTree(
return fields
}


export function parseAnyTree(
model: Model,
typeName: string,
schema: GraphQLSchema,
tree: ResolveTree
): AnyFields {
export function parseAnyTree(model: Model, typeName: string, schema: GraphQLSchema, tree: ResolveTree): AnyFields {
if (model[typeName].kind == 'interface') {
return parseQueryableTree(model, typeName, schema, tree)
} else {
Expand Down
Loading

0 comments on commit 3af413e

Please sign in to comment.