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(
|
export const edge = map(
|
||||||
x => new Edge(x),
|
x => new Edge(x),
|
||||||
bracketed(components, Bracket.Square)
|
bracketed(component, Bracket.Square)
|
||||||
)
|
)
|
||||||
|
|
||||||
const arrowRight = map(() => Direction.Right, seq(Hyphen, Bracket.Angle.Right))
|
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'
|
import { assoc, assocPath, is, nth } from '../fn.js'
|
||||||
|
|
||||||
class Value {
|
class Value {
|
||||||
|
@ -8,6 +7,10 @@ class Value {
|
||||||
this.#value = value
|
this.#value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return this.#value.toString()
|
||||||
|
}
|
||||||
|
|
||||||
get value() {
|
get value() {
|
||||||
return this.#value?.value ?? this.#value
|
return this.#value?.value ?? this.#value
|
||||||
}
|
}
|
||||||
|
@ -28,10 +31,6 @@ export class Identifier extends Value {
|
||||||
super(value)
|
super(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
|
||||||
return this.value.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
from(component) {
|
from(component) {
|
||||||
return component
|
return component
|
||||||
}
|
}
|
||||||
|
@ -189,33 +188,20 @@ export class ReturnValues {
|
||||||
|
|
||||||
#forComponentType(value, type) {
|
#forComponentType(value, type) {
|
||||||
if (this.#isTag(type)) {
|
if (this.#isTag(type)) {
|
||||||
return () => ({})
|
return {}
|
||||||
} else if (typeof type === 'function') {
|
} else if (typeof type === 'function') {
|
||||||
return type
|
return type
|
||||||
} else {
|
} else {
|
||||||
return value.from(type)
|
return entity => value.from(type)[entity]
|
||||||
//return Object.fromEntries(
|
|
||||||
// Object.entries(type).map(([k, v]) => [k, v[entity]])
|
|
||||||
//)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: adjust froms to accent entity, return data with built up objects as necessary
|
// TODO: adjust froms to accent entity, return data with built up objects as necessary
|
||||||
from(components) {
|
from(components) {
|
||||||
/*
|
const values = components.map(cmp => ({ ...cmp, rv: this.findName(cmp.name) }))
|
||||||
* const { entity, query: { components } } = node
|
.map(({ type, rv }) => new ReturnValue(rv, this.#forComponentType(rv, type)))
|
||||||
* 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(component => ({ ...component, returnValue: this.findName(component.name) }))
|
return entity => values.reduce((acc, rv) => Object.assign(acc, rv.withEntity(entity)), {})
|
||||||
.map(({ name, type, returnValue }) => ([returnValue.toString(), this.#forComponentType(returnValue, type)]))
|
|
||||||
console.log(this, values)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
find(fn) {
|
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 {
|
export class KeyValuePair {
|
||||||
constructor(key, value) {
|
constructor(key, value) {
|
||||||
this.key = key
|
this.key = key
|
||||||
|
|
34
src/query.js
34
src/query.js
|
@ -26,7 +26,7 @@ const prepareQuery = (query, component) => {
|
||||||
} else {
|
} else {
|
||||||
const components = match.components.map(nodeComponent(component))
|
const components = match.components.map(nodeComponent(component))
|
||||||
const types = components.filter(notEntity).map(prop('type'))
|
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 resolveNode = curry((node, obj) => {
|
||||||
const returns = path('query.schema.returnValues', node)
|
const { entity, query: { getReturns } } = node
|
||||||
const { entity, query: { components } } = node
|
return { ...obj, ...getReturns(entity) }
|
||||||
// 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 resolveRelationship = edges => {
|
const resolveRelationship = edges => {
|
||||||
|
|
|
@ -55,6 +55,7 @@ describe('query', () => {
|
||||||
relate(world, b, Knows, a) // 9
|
relate(world, b, Knows, a) // 9
|
||||||
relate(world, c, Knows, player) // 10
|
relate(world, c, Knows, player) // 10
|
||||||
|
|
||||||
|
// tag components should return an object object
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
query('MATCH (player:Player) RETURN player', engine).unwrap(),
|
query('MATCH (player:Player) RETURN player', engine).unwrap(),
|
||||||
[{ player: {} }]
|
[{ player: {} }]
|
||||||
|
|
Loading…
Reference in a new issue