allow multiple component matching and entity id binding
This commit is contained in:
parent
c1520b7a59
commit
28ea665212
4 changed files with 29 additions and 55 deletions
|
@ -46,7 +46,7 @@ export const node = map(
|
|||
|
||||
export const edge = map(
|
||||
x => new Edge(x),
|
||||
bracketed(components, Bracket.Square)
|
||||
bracketed(component, Bracket.Square)
|
||||
)
|
||||
|
||||
const arrowRight = map(() => Direction.Right, seq(Hyphen, Bracket.Angle.Right))
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { pipe } from 'bitecs'
|
||||
import { assoc, assocPath, is, nth } from '../fn.js'
|
||||
|
||||
class Value {
|
||||
|
@ -8,6 +7,10 @@ class Value {
|
|||
this.#value = value
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.#value.toString()
|
||||
}
|
||||
|
||||
get value() {
|
||||
return this.#value?.value ?? this.#value
|
||||
}
|
||||
|
@ -28,10 +31,6 @@ export class Identifier extends Value {
|
|||
super(value)
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.value.toString()
|
||||
}
|
||||
|
||||
from(component) {
|
||||
return component
|
||||
}
|
||||
|
@ -189,33 +188,20 @@ export class ReturnValues {
|
|||
|
||||
#forComponentType(value, type) {
|
||||
if (this.#isTag(type)) {
|
||||
return () => ({})
|
||||
return {}
|
||||
} else if (typeof type === 'function') {
|
||||
return type
|
||||
} else {
|
||||
return value.from(type)
|
||||
//return Object.fromEntries(
|
||||
// Object.entries(type).map(([k, v]) => [k, v[entity]])
|
||||
//)
|
||||
return entity => value.from(type)[entity]
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: adjust froms to accent entity, return data with built up objects as necessary
|
||||
from(components) {
|
||||
/*
|
||||
* const { entity, query: { components } } = node
|
||||
* const returns2 = components.map(c => ({ ...c, returnValue: returns.find(x => x.equals(c.name)) }))
|
||||
* returns2.map(({ returnValue, type }) => getValue(returnValue, type, entity))
|
||||
* const values = returns2.filter(({ name }) => returns.includes(name))
|
||||
* .map(({ name, type, returnValue }) => ({ [name]: getValue(returnValue, type, entity) }))
|
||||
* const values = components.filter(({ name }) => returns.includes(name))
|
||||
* .map(({ name, type }) => ({ [name]: getValue(type, entity) }))
|
||||
* return Object.assign(obj, ...values)
|
||||
*/
|
||||
const values = components.map(cmp => ({ ...cmp, rv: this.findName(cmp.name) }))
|
||||
.map(({ type, rv }) => new ReturnValue(rv, this.#forComponentType(rv, type)))
|
||||
|
||||
const values = components.map(component => ({ ...component, returnValue: this.findName(component.name) }))
|
||||
.map(({ name, type, returnValue }) => ([returnValue.toString(), this.#forComponentType(returnValue, type)]))
|
||||
console.log(this, values)
|
||||
return entity => values.reduce((acc, rv) => Object.assign(acc, rv.withEntity(entity)), {})
|
||||
}
|
||||
|
||||
find(fn) {
|
||||
|
@ -235,6 +221,21 @@ export class ReturnValues {
|
|||
}
|
||||
}
|
||||
|
||||
class ReturnValue {
|
||||
#value
|
||||
#getter
|
||||
|
||||
constructor(value, getter) {
|
||||
this.#value = value
|
||||
this.#getter = getter
|
||||
}
|
||||
|
||||
withEntity(entity) {
|
||||
return assocPath(this.#value.toString(), this.#getter(entity), {})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class KeyValuePair {
|
||||
constructor(key, value) {
|
||||
this.key = key
|
||||
|
|
34
src/query.js
34
src/query.js
|
@ -26,7 +26,7 @@ const prepareQuery = (query, component) => {
|
|||
} else {
|
||||
const components = match.components.map(nodeComponent(component))
|
||||
const types = components.filter(notEntity).map(prop('type'))
|
||||
return { components, relationship, query: defineQuery(types), schema: query }
|
||||
return { components, relationship, getReturns: returnValues.from(components), query: defineQuery(types), schema: query }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,38 +95,10 @@ const executeQuery = curry((query, world) => {
|
|||
}
|
||||
})
|
||||
|
||||
const isTag = type => (
|
||||
type && Object.getOwnPropertySymbols(type).find(
|
||||
(s) => s.description === 'tagStore'
|
||||
) || false
|
||||
)
|
||||
|
||||
const getValue = (returnValue, type, entity) => {
|
||||
if (isTag(type)) {
|
||||
return {}
|
||||
} else if (typeof type === 'function') {
|
||||
return type(entity)
|
||||
} else {
|
||||
return returnValue.from(type)
|
||||
//return Object.fromEntries(
|
||||
// Object.entries(type).map(([k, v]) => [k, v[entity]])
|
||||
//)
|
||||
}
|
||||
}
|
||||
|
||||
const resolveNode = curry((node, obj) => {
|
||||
const returns = path('query.schema.returnValues', node)
|
||||
const { entity, query: { components } } = node
|
||||
// TODO: do this work in prepareQuery
|
||||
returns.from(components)
|
||||
|
||||
//const returns2 = components.map(c => ({ ...c, returnValue: returns.find(x => x.equals(c.name)) }))
|
||||
//returns2.map(({ returnValue, type }) => getValue(returnValue, type, entity))
|
||||
//const values = returns2.filter(({ name }) => returns.includes(name))
|
||||
// .map(({ name, type, returnValue }) => ({ [name]: getValue(returnValue, type, entity) }))
|
||||
//const values = components.filter(({ name }) => returns.includes(name))
|
||||
// .map(({ name, type }) => ({ [name]: getValue(type, entity) }))
|
||||
//return Object.assign(obj, ...values)
|
||||
const { entity, query: { getReturns } } = node
|
||||
return { ...obj, ...getReturns(entity) }
|
||||
})
|
||||
|
||||
const resolveRelationship = edges => {
|
||||
|
|
|
@ -55,6 +55,7 @@ describe('query', () => {
|
|||
relate(world, b, Knows, a) // 9
|
||||
relate(world, c, Knows, player) // 10
|
||||
|
||||
// tag components should return an object object
|
||||
assert.deepEqual(
|
||||
query('MATCH (player:Player) RETURN player', engine).unwrap(),
|
||||
[{ player: {} }]
|
||||
|
|
Loading…
Reference in a new issue