Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
moodlenet
nodejs-services
Commits
2650bc00
Commit
2650bc00
authored
Oct 07, 2020
by
aleclofabbro
Browse files
almost there !
parent
e3b40674
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/gql-graph/buildDocumentSelection.ts
View file @
2650bc00
...
...
@@ -18,7 +18,7 @@ export const buildDocumentSelection = (qObj: GraphQueryObj): DocumentSelection |
return
null
}
const
documentValueFieldsSelections
=
qObj
.
select
.
reduce
((
_documentSelection
,
selection
)
=>
{
const
valueField
:
ValueField
=
{
fieldName
:
selection
.
field
}
const
valueField
:
ValueField
=
selection
return
{
...
_documentSelection
,
[
selection
.
alias
]:
valueField
,
...
...
@@ -27,7 +27,7 @@ export const buildDocumentSelection = (qObj: GraphQueryObj): DocumentSelection |
const
documentUnionLookupFieldSelections
=
qObj
.
traverse
.
reduce
(
(
_documentSelection
,
qObjSelection
)
=>
{
const
_existingAlias
=
_documentSelection
[
qObjSelection
.
alias
]
if
(
_existingAlias
&&
'
fieldName
'
in
_existingAlias
)
{
if
(
_existingAlias
&&
!
isUnionLookupField
(
_existingAlias
)
)
{
throw
aliasConflictError
(
qObjSelection
,
qObj
)
}
const
select
=
buildDocumentSelection
(
qObjSelection
)
...
...
@@ -37,7 +37,13 @@ export const buildDocumentSelection = (qObj: GraphQueryObj): DocumentSelection |
const
unionLookupField
:
UnionLookupField
=
_existingAlias
||
(
_documentSelection
[
qObjSelection
.
alias
]
=
{
page
:
qObjSelection
.
page
,
lookups
:
[]
})
(
_documentSelection
[
qObjSelection
.
alias
]
=
{
page
:
qObjSelection
.
page
,
fieldName
:
qObjSelection
.
fieldName
,
alias
:
qObjSelection
.
alias
,
lookups
:
[],
traverseRelation
:
qObjSelection
.
traverseRelation
,
})
unionLookupField
.
lookups
.
push
({
__typename
:
qObjSelection
.
__typename
,
...
...
@@ -63,5 +69,4 @@ const aliasConflictError = (selection: GraphQueryObj, par: GraphQueryObj) => {
return
new
Error
(
`A ValueField can't have same alias[
${
selection
.
alias
}
] as a UnionLookupField`
)
}
export
const
isValueField
=
(
_
:
Field
):
_
is
ValueField
=>
!!
(
_
&&
'
fieldName
'
in
_
)
export
const
isUnionLookupField
=
(
_
:
Field
):
_
is
UnionLookupField
=>
!!
(
_
&&
'
lookups
'
in
_
)
src/gql-graph/defaultGraphFieldResolver.ts
View file @
2650bc00
...
...
@@ -2,10 +2,11 @@ import { Context } from '../gql'
import
{
ResolverFn
}
from
'
../gql/types
'
import
{
ShallowTypeMocks
}
from
'
../gql/shallowTypes
'
import
{
typeInfo
,
getParent
}
from
'
./graphQuery
'
import
{
GraphQueryObj
}
from
'
./types
'
import
{
GraphQueryObj
,
TraverseRelation
}
from
'
./types
'
export
function
defaultGraphFieldResolver
():
ResolverFn
<
any
,
any
,
Context
,
any
>
{
return
(
parent
,
args
,
context
,
info
)
=>
{
const
{
fieldName
,
parentType
,
returnType
,
schema
}
=
info
if
(
!
context
.
$graph
)
{
context
.
$graph
=
{
qObj
:
{
...
...
@@ -13,11 +14,12 @@ export function defaultGraphFieldResolver(): ResolverFn<any, any, Context, any>
alias
:
'
Query
'
,
directives
:
{},
traverse
:
[],
traverseRelation
:
null
,
fieldName
:
fieldName
,
select
:
[],
},
}
}
const
{
fieldName
,
parentType
,
returnType
,
schema
}
=
info
console
.
log
(
`defaultFieldResolver `
,
{
parent
,
parentTypeName
:
parentType
.
name
,
...
...
@@ -37,7 +39,7 @@ export function defaultGraphFieldResolver(): ResolverFn<any, any, Context, any>
if
(
!
parentQ
)
{
throw
new
Error
(
'
defaultFieldResolver no parentQ
'
)
}
if
(
isTop
||
[
'
_rel
'
,
'
_subj
'
,
'
_obj
'
].
includes
(
fieldName
))
{
if
(
isTop
||
isTraverseRelation
(
fieldName
))
{
parentQ
.
traverse
.
push
(
...
__typenames
.
map
<
GraphQueryObj
>
((
__typename
)
=>
({
__typename
,
...
...
@@ -46,7 +48,9 @@ export function defaultGraphFieldResolver(): ResolverFn<any, any, Context, any>
page
:
args
?.
page
,
select
:
[],
traverse
:
[],
traverseRelation
:
isTraverseRelation
(
fieldName
)
?
fieldName
:
null
,
directives
:
{},
fieldName
:
fieldName
,
}))
)
...
...
@@ -62,9 +66,12 @@ export function defaultGraphFieldResolver(): ResolverFn<any, any, Context, any>
return
fieldReturn
}
else
{
if
(
'
string
'
==
typeof
info
.
path
.
key
)
{
parentQ
.
select
.
push
({
field
:
fieldName
,
alias
:
info
.
path
.
key
})
parentQ
.
select
.
push
({
field
Name
:
fieldName
,
alias
:
info
.
path
.
key
})
}
return
parent
[
fieldName
]
}
}
}
const
isTraverseRelation
=
(
_
:
string
):
_
is
TraverseRelation
=>
[
'
_subj
'
,
'
_obj
'
,
'
_rel
'
].
includes
(
_
)
src/gql-graph/mongo/buildMongoPipeline.ts
View file @
2650bc00
import
{
DocumentSelection
}
from
'
../types
'
import
{
is
Value
Field
}
from
'
../
queryBuilder
'
export
const
buildMongoPipeline
=
(
docS
:
DocumentSelection
)
=>
{
import
{
is
UnionLookup
Field
}
from
'
../
buildDocumentSelection
'
export
const
buildMongoPipeline
=
(
docS
:
DocumentSelection
,
notTop
?:
boolean
)
=>
{
const
lookups
=
[]
as
any
[]
const
project
=
{}
as
Record
<
string
,
string
>
Object
.
entries
(
docS
).
forEach
(([
alias
,
field
])
=>
{
if
(
isValueField
(
field
))
{
project
[
field
.
fieldName
]
=
alias
}
else
{
const
$match
=
{
$and
:
[]
as
any
[]
}
const
$unionWith
=
{
coll
:
'
Graph
'
,
pipeline
:
[{
$match
}]
as
any
[],
}
if
(
isUnionLookupField
(
field
))
{
const
$mainMatchUnionMatch
=
{
$or
:
[]
as
any
[]
}
const
$mainMatch
=
{
$and
:
[
$mainMatchUnionMatch
]
}
const
pipeline
=
[{
$match
:
$mainMatch
}]
as
any
[]
const
$lookup
=
{
as
:
alias
,
as
:
field
.
alias
,
let
:
{}
as
Record
<
string
,
string
>
,
from
:
'
Graph
'
,
pipeline
:
[{
$unionWith
}],
pipeline
,
}
if
(
field
.
traverseRelation
)
{
if
(
field
.
traverseRelation
===
'
_rel
'
)
{
$lookup
.
let
.
nodeId
=
'
$_id
'
notTop
&&
$mainMatch
.
$and
.
push
({
// $expr: { $eq: [`$${field.traverseRelation}`, '$$nodeId'] },
$expr
:
{
$eq
:
[
`$_subj`
,
'
$$nodeId
'
]
},
}
as
any
)
}
else
{
$lookup
.
let
.
edgeSide
=
`$
${
field
.
traverseRelation
}
`
//=== '_obj' ? '$_subj' : '$_obj'
notTop
&&
$mainMatch
.
$and
.
push
({
$expr
:
{
$eq
:
[
`$_id`
,
'
$$edgeSide
'
]
}
}
as
any
)
}
}
field
.
lookups
.
forEach
((
fieldLookup
)
=>
{
$match
.
$and
.
push
({
__typename
:
fieldLookup
.
__typename
})
const
$match
=
{
$and
:
[{
__typename
:
fieldLookup
.
__typename
}]
as
any
[]
}
$mainMatchUnionMatch
.
$or
.
push
(
$match
)
fieldLookup
.
match
&&
$match
.
$and
.
push
(
fieldLookup
.
match
)
const
pipeline
=
buildMongoPipeline
(
fieldLookup
.
select
)
$unionWith
.
pipeline
.
push
(...
pipeline
)
pipeline
.
push
(...
buildMongoPipeline
(
fieldLookup
.
select
,
true
))
})
project
[
field
.
alias
]
=
`$
${
field
.
alias
}
`
lookups
.
push
({
$lookup
,
})
}
else
{
project
[
alias
]
=
`$
${
field
.
fieldName
}
`
}
})
const
stages
=
[...
lookups
]
if
(
Object
.
keys
(
project
).
length
)
{
stages
.
push
({
$project
:
project
})
if
(
notTop
)
{
const
stages
=
[...
lookups
]
if
(
Object
.
keys
(
project
).
length
)
{
stages
.
push
({
$project
:
project
})
}
return
stages
}
else
{
const
stages
=
lookups
[
0
].
$lookup
.
pipeline
return
stages
}
return
stages
}
src/gql-graph/types.d.ts
View file @
2650bc00
...
...
@@ -7,14 +7,17 @@ export type GqlType = { id: string; __typename: string }
export
type
GqlNode
=
GqlType
&
{
_rel
:
any
[]
}
export
type
GqlRelation
=
GqlType
&
{
_obj
:
any
;
_subj
:
any
}
export
type
TraverseRelation
=
'
_obj
'
|
'
_subj
'
|
'
_rel
'
// GraphQuery
export
type
GraphQuery
=
{
qObj
:
GraphQueryObj
}
export
type
GraphQueryObj
=
{
export
type
GraphQueryObj
=
Selection
&
{
__typename
:
string
traverseRelation
:
TraverseRelation
|
null
match
?:
any
page
?:
{
limit
?:
number
...
...
@@ -23,11 +26,10 @@ export type GraphQueryObj = {
directives
:
Record
<
string
,
any
>
select
:
Selection
[]
traverse
:
GraphQueryObj
[]
alias
:
string
}
export
type
Selection
=
{
field
:
string
field
Name
:
string
alias
:
string
}
export
type
Match
=
any
...
...
@@ -41,15 +43,14 @@ export type DocumentSelection = {
export
type
Field
=
UnionLookupField
|
ValueField
export
type
ValueField
=
{
fieldName
:
string
}
export
type
ValueField
=
Selection
export
type
UnionLookupField
=
{
export
type
UnionLookupField
=
ValueField
&
{
page
?:
{
limit
?:
number
after
?:
string
|
ObjectID
}
traverseRelation
:
TraverseRelation
|
null
lookups
:
FieldLookup
[]
}
...
...
src/http/index.ts
View file @
2650bc00
...
...
@@ -3,8 +3,8 @@ import { ApolloServer } from 'apollo-server-express'
import
express
from
'
express
'
import
{
graphql
,
GraphQLSchema
}
from
'
graphql
'
import
{
Context
}
from
'
../gql
'
import
{
buildMongoPipeline
}
from
'
../gql-graph/mongo/buildMongo
Query
'
import
{
buildQueryDocumentSelection
}
from
'
../gql-graph/
queryBuilder
'
import
{
buildMongoPipeline
}
from
'
../gql-graph/mongo/buildMongo
Pipeline
'
import
{
buildQueryDocumentSelection
}
from
'
../gql-graph/
buildDocumentSelection
'
import
{
collection
}
from
'
../mongo/collection
'
type
Cfg
=
{
...
...
@@ -28,7 +28,7 @@ const executor: GraphQLServerOptions['executor'] = async (requestContext) => {
console
.
dir
({
'
executor documentSelection
'
:
documentSelection
},
{
depth
:
15
})
if
(
documentSelection
)
{
const
pipeline
=
buildMongoPipeline
(
documentSelection
)
console
.
dir
({
'
executor pipeline
'
:
pipeline
},
{
depth
:
15
}
)
console
.
log
(
'
executor pipeline
'
,
JSON
.
stringify
(
pipeline
,
null
,
4
)
)
const
c
=
await
collection
<
any
>
()
return
{
data
:
await
c
.
aggregate
(
pipeline
).
toArray
()
}
}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment