/
Ref.ts
104 lines (84 loc) · 2.69 KB
/
Ref.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/** @module protopipe */
import {
IId,
ISpaceElement,
ISpaceOperator,
ISpace,
} from '../types'
import {CrudStackOperator} from '../../stack/operator'
import {
IAny,
TPredicate,
} from '../../types'
import {IStackValueUpdateReducer} from '../../stack/operator/Crud'
import {IStack} from '../../stack'
import {genId} from '../../util'
export interface IReference extends ISpaceElement {
type: 'REF',
value: {
from: IId,
to: IId
}
}
export type IDirection = 'from' | 'to'
export class RefOperator implements ISpaceOperator<ISpace> {
space: ISpace
constructor(space: ISpace) {
this.space = space
}
static create(space: ISpace, type: string, value: IAny): ISpaceElement {
const stack: IStack<ISpaceElement> = space.value
const elt: ISpaceElement = {
id: genId(type),
type,
value,
}
return CrudStackOperator.create(stack, elt)
}
static upsert(space: ISpace, type: string, value: IAny, predicate?: TPredicate): ISpaceElement {
const stack = space.value
const elt: ISpaceElement = {
id: genId(type),
type,
value,
}
const reducer: IStackValueUpdateReducer = (prev, next) => ({...prev, ...next, id: prev.id})
return CrudStackOperator.update(
stack,
predicate,
elt,
true,
reducer,
)
}
static getRefs(space: ISpace, id: IId | IId[], direction: IDirection = 'from'): ISpaceElement[] {
const ids = Array.isArray(id) ? id : [id]
return CrudStackOperator.read(
space.value,
(item) => item.type === 'REF' && ids.includes(item.value[direction]),
)
}
static get(space: ISpace, id: IId, type?: string): ISpaceElement | undefined {
return CrudStackOperator.read(space.value, ({id: _id, type: _type}) => id === _id && (type ? type === _type : true), 1)[0]
}
static getRels(space: ISpace, id: IId, direction: IDirection = 'from'): ISpaceElement[] {
const refs = this.getRefs(space, id, direction)
const _direction: IDirection = direction === 'from' ? 'to' : 'from'
const ids = refs.map(ref => ref.value[_direction])
return CrudStackOperator.read(space.value, item => ids.includes(item.id))
}
static link(space: ISpace, from: IId, to: IId) {
const type = 'REF'
const value = {
from,
to,
}
return this.upsert(space, type, value, (item: ISpaceElement) => item.type === type && item.value.from === from && item.value.to === to)
}
static read(predicate: TPredicate, space: ISpace, limit?: number): ISpaceElement[] {
return CrudStackOperator.read(space.value, predicate, limit)
}
static find(predicate: TPredicate, space: ISpace): ISpaceElement | undefined {
return this.read(predicate, space, 1)[0]
}
}