@opendaw/lib-box 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/address.d.ts +47 -0
- package/dist/address.d.ts.map +1 -0
- package/dist/address.js +133 -0
- package/dist/array.d.ts +19 -0
- package/dist/array.d.ts.map +1 -0
- package/dist/array.js +32 -0
- package/dist/box.d.ts +51 -0
- package/dist/box.d.ts.map +1 -0
- package/dist/box.js +122 -0
- package/dist/dispatchers.d.ts +16 -0
- package/dist/dispatchers.d.ts.map +1 -0
- package/dist/dispatchers.js +127 -0
- package/dist/editing.d.ts +21 -0
- package/dist/editing.d.ts.map +1 -0
- package/dist/editing.js +131 -0
- package/dist/field.d.ts +42 -0
- package/dist/field.d.ts.map +1 -0
- package/dist/field.js +80 -0
- package/dist/graph-edges.d.ts +16 -0
- package/dist/graph-edges.d.ts.map +1 -0
- package/dist/graph-edges.js +109 -0
- package/dist/graph.d.ts +55 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +262 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/object.d.ts +17 -0
- package/dist/object.d.ts.map +1 -0
- package/dist/object.js +19 -0
- package/dist/pointer-hub.d.ts +26 -0
- package/dist/pointer-hub.d.ts.map +1 -0
- package/dist/pointer-hub.js +110 -0
- package/dist/pointer.d.ts +32 -0
- package/dist/pointer.d.ts.map +1 -0
- package/dist/pointer.js +82 -0
- package/dist/primitive.d.ts +110 -0
- package/dist/primitive.d.ts.map +1 -0
- package/dist/primitive.js +152 -0
- package/dist/serializer.d.ts +7 -0
- package/dist/serializer.d.ts.map +1 -0
- package/dist/serializer.js +29 -0
- package/dist/sync-source.d.ts +11 -0
- package/dist/sync-source.d.ts.map +1 -0
- package/dist/sync-source.js +72 -0
- package/dist/sync-target.d.ts +5 -0
- package/dist/sync-target.d.ts.map +1 -0
- package/dist/sync-target.js +40 -0
- package/dist/sync.d.ts +24 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +1 -0
- package/dist/updates.d.ts +70 -0
- package/dist/updates.d.ts.map +1 -0
- package/dist/updates.js +178 -0
- package/dist/vertex.d.ts +41 -0
- package/dist/vertex.d.ts.map +1 -0
- package/dist/vertex.js +1 -0
- package/package.json +33 -0
package/dist/editing.js
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
import { Arrays, assert, Option } from "@opendaw/lib-std";
|
2
|
+
class EditingStep {
|
3
|
+
updates;
|
4
|
+
constructor(updates) {
|
5
|
+
this.updates = updates;
|
6
|
+
}
|
7
|
+
undo(graph) {
|
8
|
+
for (const update of this.updates.toReversed()) {
|
9
|
+
update.inverse(graph);
|
10
|
+
}
|
11
|
+
}
|
12
|
+
redo(graph) {
|
13
|
+
for (const update of this.updates) {
|
14
|
+
update.forward(graph);
|
15
|
+
}
|
16
|
+
}
|
17
|
+
}
|
18
|
+
export class Editing {
|
19
|
+
#graph;
|
20
|
+
#pending = [];
|
21
|
+
#history = [];
|
22
|
+
#modifying = false;
|
23
|
+
#historyIndex = 0;
|
24
|
+
constructor(graph) {
|
25
|
+
this.#graph = graph;
|
26
|
+
}
|
27
|
+
get graph() { return this.#graph; }
|
28
|
+
isEmpty() { return this.#history.length === 0 && this.#pending.length === 0; }
|
29
|
+
clear() {
|
30
|
+
assert(!this.#modifying, "Already modifying");
|
31
|
+
Arrays.clear(this.#pending);
|
32
|
+
Arrays.clear(this.#history);
|
33
|
+
this.#historyIndex = 0;
|
34
|
+
}
|
35
|
+
undo() {
|
36
|
+
if (this.#pending.length > 0) {
|
37
|
+
this.mark();
|
38
|
+
}
|
39
|
+
if (this.#historyIndex === 0) {
|
40
|
+
return false;
|
41
|
+
}
|
42
|
+
this.#graph.beginTransaction();
|
43
|
+
const editingStep = this.#history[--this.#historyIndex];
|
44
|
+
editingStep.undo(this.#graph);
|
45
|
+
this.#graph.endTransaction();
|
46
|
+
this.#graph.edges().validateRequirements();
|
47
|
+
return true;
|
48
|
+
}
|
49
|
+
redo() {
|
50
|
+
if (this.#historyIndex === this.#history.length) {
|
51
|
+
return false;
|
52
|
+
}
|
53
|
+
if (this.#pending.length > 0) {
|
54
|
+
console.warn("redo while having pending updates?");
|
55
|
+
return false;
|
56
|
+
}
|
57
|
+
this.#graph.beginTransaction();
|
58
|
+
this.#history[this.#historyIndex++].redo(this.#graph);
|
59
|
+
this.#graph.endTransaction();
|
60
|
+
this.#graph.edges().validateRequirements();
|
61
|
+
return true;
|
62
|
+
}
|
63
|
+
// TODO This is an option to clarify, if user actions meant to be run by a modifier or not.
|
64
|
+
// See ParameterWrapper. Not the nicest solution. Probably coming back to this sooner or later.
|
65
|
+
canModify() { return !this.#graph.inTransaction(); }
|
66
|
+
modify(modifier, mark = true) {
|
67
|
+
if (this.#modifying) {
|
68
|
+
// we just keep adding new updates to the running modifier
|
69
|
+
return Option.wrap(modifier());
|
70
|
+
}
|
71
|
+
if (mark && this.#pending.length > 0) {
|
72
|
+
this.mark();
|
73
|
+
}
|
74
|
+
const result = Option.wrap(this.#modify(modifier));
|
75
|
+
if (mark) {
|
76
|
+
this.mark();
|
77
|
+
}
|
78
|
+
return result;
|
79
|
+
}
|
80
|
+
beginModification() {
|
81
|
+
this.#graph.beginTransaction();
|
82
|
+
this.#modifying = true;
|
83
|
+
const subscription = this.#graph.subscribeToAllUpdates({
|
84
|
+
onUpdate: (update) => this.#pending.push(update)
|
85
|
+
});
|
86
|
+
const complete = () => {
|
87
|
+
this.#graph.endTransaction();
|
88
|
+
subscription.terminate();
|
89
|
+
this.#modifying = false;
|
90
|
+
this.#graph.edges().validateRequirements();
|
91
|
+
};
|
92
|
+
return {
|
93
|
+
approve: () => { complete(); },
|
94
|
+
revert: () => {
|
95
|
+
this.clearPending();
|
96
|
+
complete();
|
97
|
+
}
|
98
|
+
};
|
99
|
+
}
|
100
|
+
#modify(modifier) {
|
101
|
+
assert(!this.#modifying, "Already modifying");
|
102
|
+
this.#modifying = true;
|
103
|
+
const subscription = this.#graph.subscribeToAllUpdates({
|
104
|
+
onUpdate: (update) => this.#pending.push(update)
|
105
|
+
});
|
106
|
+
this.#graph.beginTransaction();
|
107
|
+
const result = modifier();
|
108
|
+
this.#graph.endTransaction();
|
109
|
+
subscription.terminate();
|
110
|
+
this.#modifying = false;
|
111
|
+
this.#graph.edges().validateRequirements();
|
112
|
+
return result;
|
113
|
+
}
|
114
|
+
mark() {
|
115
|
+
if (this.#pending.length === 0) {
|
116
|
+
return;
|
117
|
+
}
|
118
|
+
if (this.#history.length - this.#historyIndex > 0) {
|
119
|
+
this.#history.splice(this.#historyIndex);
|
120
|
+
}
|
121
|
+
this.#history.push(new EditingStep(this.#pending.splice(0)));
|
122
|
+
this.#historyIndex = this.#history.length;
|
123
|
+
}
|
124
|
+
clearPending() {
|
125
|
+
if (this.#pending.length === 0) {
|
126
|
+
return;
|
127
|
+
}
|
128
|
+
this.#pending.reverse().forEach(update => update.inverse(this.#graph));
|
129
|
+
this.#pending.length = 0;
|
130
|
+
}
|
131
|
+
}
|
package/dist/field.d.ts
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
import { DataInput, DataOutput, Nullish, Option, short } from "@opendaw/lib-std";
|
2
|
+
import { Address } from "./address";
|
3
|
+
import { Box } from "./box";
|
4
|
+
import { PointerRules, Vertex, VertexVisitor } from "./vertex";
|
5
|
+
import { PointerTypes } from "./pointer";
|
6
|
+
import { PointerHub } from "./pointer-hub";
|
7
|
+
import { BoxGraph } from "./graph";
|
8
|
+
export type FieldKey = number;
|
9
|
+
export type FieldKeys = Readonly<Int16Array>;
|
10
|
+
export type Fields = Record<FieldKey, Field>;
|
11
|
+
export type FieldConstruct<T extends PointerTypes> = {
|
12
|
+
parent: Vertex;
|
13
|
+
fieldKey: FieldKey;
|
14
|
+
fieldName: string;
|
15
|
+
pointerRules: PointerRules<T>;
|
16
|
+
};
|
17
|
+
export declare class Field<P extends PointerTypes = PointerTypes, F extends Fields = Fields> implements Vertex<P, F> {
|
18
|
+
#private;
|
19
|
+
static hook<P extends PointerTypes>(construct: FieldConstruct<P>): Field<P, Fields>;
|
20
|
+
protected constructor({ parent, fieldKey, fieldName, pointerRules }: FieldConstruct<P>);
|
21
|
+
accept<RETURN>(visitor: VertexVisitor<RETURN>): Nullish<RETURN>;
|
22
|
+
get box(): Box;
|
23
|
+
get graph(): BoxGraph;
|
24
|
+
get parent(): Vertex;
|
25
|
+
get fieldKey(): short;
|
26
|
+
get fieldName(): string;
|
27
|
+
get pointerRules(): PointerRules<P>;
|
28
|
+
get pointerHub(): PointerHub;
|
29
|
+
get address(): Address;
|
30
|
+
get debugPath(): string;
|
31
|
+
isBox(): this is Box;
|
32
|
+
isField(): this is Field;
|
33
|
+
isAttached(): boolean;
|
34
|
+
fields(): Iterable<Field>;
|
35
|
+
getField(_key: keyof F): F[keyof F];
|
36
|
+
optField(_key: keyof F): Option<F[keyof F]>;
|
37
|
+
read(_input: DataInput): void;
|
38
|
+
write(_output: DataOutput): void;
|
39
|
+
disconnect(): void;
|
40
|
+
toString(): string;
|
41
|
+
}
|
42
|
+
//# sourceMappingURL=field.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../src/field.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,UAAU,EAAmB,OAAO,EAAE,MAAM,EAAsB,KAAK,EAAC,MAAM,kBAAkB,CAAA;AACnH,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AACjC,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAA;AACzB,OAAO,EAAC,YAAY,EAAE,MAAM,EAAE,aAAa,EAAC,MAAM,UAAU,CAAA;AAC5D,OAAO,EAAC,YAAY,EAAC,MAAM,WAAW,CAAA;AACtC,OAAO,EAAC,UAAU,EAAC,MAAM,eAAe,CAAA;AACxC,OAAO,EAAC,QAAQ,EAAC,MAAM,SAAS,CAAA;AAEhC,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAA;AAC7B,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAA;AAC5C,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;AAC5C,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,YAAY,IAAI;IACjD,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,QAAQ,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAA;CAChC,CAAA;AAED,qBAAa,KAAK,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,YAAW,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;;IACxG,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,YAAY,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC;IAShE,SAAS,aAAa,EAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAC,EAAE,cAAc,CAAC,CAAC,CAAC;IASpF,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAI/D,IAAI,GAAG,IAAI,GAAG,CAA0B;IACxC,IAAI,KAAK,IAAI,QAAQ,CAA4B;IACjD,IAAI,MAAM,IAAI,MAAM,CAAsB;IAC1C,IAAI,QAAQ,IAAI,KAAK,CAAwB;IAC7C,IAAI,SAAS,IAAI,MAAM,CAAyB;IAChD,IAAI,YAAY,IAAI,YAAY,CAAC,CAAC,CAAC,CAA4B;IAE/D,IACI,UAAU,IAAI,UAAU,CAA8B;IAE1D,IACI,OAAO,IAAI,OAAO,CAAqD;IAE3E,IACI,SAAS,IAAI,MAAM,CAEtB;IAED,KAAK,IAAI,IAAI,IAAI,GAAG;IACpB,OAAO,IAAI,IAAI,IAAI,KAAK;IACxB,UAAU,IAAI,OAAO;IACrB,MAAM,IAAI,QAAQ,CAAC,KAAK,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3C,IAAI,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAC7B,KAAK,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI;IAChC,UAAU,IAAI,IAAI;IAUlB,QAAQ,IAAI,MAAM;CACrB"}
|
package/dist/field.js
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
6
|
+
};
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
9
|
+
};
|
10
|
+
import { Iterables, Lazy, Option, panic, safeExecute } from "@opendaw/lib-std";
|
11
|
+
import { Address } from "./address";
|
12
|
+
import { PointerHub } from "./pointer-hub";
|
13
|
+
export class Field {
|
14
|
+
static hook(construct) {
|
15
|
+
return new Field(construct);
|
16
|
+
}
|
17
|
+
#parent;
|
18
|
+
#fieldKey;
|
19
|
+
#fieldName;
|
20
|
+
#pointerRules;
|
21
|
+
constructor({ parent, fieldKey, fieldName, pointerRules }) {
|
22
|
+
this.#parent = parent;
|
23
|
+
this.#fieldKey = fieldKey;
|
24
|
+
this.#fieldName = fieldName;
|
25
|
+
this.#pointerRules = pointerRules;
|
26
|
+
if (pointerRules.mandatory) {
|
27
|
+
this.graph.edges().watchVertex(this);
|
28
|
+
}
|
29
|
+
}
|
30
|
+
accept(visitor) {
|
31
|
+
return safeExecute(visitor.visitField, this);
|
32
|
+
}
|
33
|
+
get box() { return this.#parent.box; }
|
34
|
+
get graph() { return this.#parent.graph; }
|
35
|
+
get parent() { return this.#parent; }
|
36
|
+
get fieldKey() { return this.#fieldKey; }
|
37
|
+
get fieldName() { return this.#fieldName; }
|
38
|
+
get pointerRules() { return this.#pointerRules; }
|
39
|
+
get pointerHub() { return new PointerHub(this); }
|
40
|
+
get address() { return this.#parent.address.append(this.#fieldKey); }
|
41
|
+
get debugPath() {
|
42
|
+
return `${this.box.name}:${this.box.mapFields(field => field.fieldName, ...this.address.fieldKeys).join("/")}`;
|
43
|
+
}
|
44
|
+
isBox() { return false; }
|
45
|
+
isField() { return true; }
|
46
|
+
isAttached() { return this.graph.findBox(this.address.uuid).nonEmpty(); }
|
47
|
+
fields() { return Iterables.empty(); }
|
48
|
+
getField(_key) { return panic(); }
|
49
|
+
optField(_key) { return Option.None; }
|
50
|
+
read(_input) { }
|
51
|
+
write(_output) { }
|
52
|
+
disconnect() {
|
53
|
+
if (this.pointerHub.isEmpty()) {
|
54
|
+
return;
|
55
|
+
}
|
56
|
+
const incoming = this.pointerHub.incoming();
|
57
|
+
incoming.forEach(pointer => {
|
58
|
+
pointer.defer();
|
59
|
+
if (pointer.mandatory || (this.pointerRules.mandatory && incoming.length === 1)) {
|
60
|
+
pointer.box.delete();
|
61
|
+
}
|
62
|
+
});
|
63
|
+
}
|
64
|
+
toString() { return `{${this.box.constructor.name}:${this.constructor.name} (${this.fieldName}) ${this.address.toString()}`; }
|
65
|
+
}
|
66
|
+
__decorate([
|
67
|
+
Lazy,
|
68
|
+
__metadata("design:type", PointerHub),
|
69
|
+
__metadata("design:paramtypes", [])
|
70
|
+
], Field.prototype, "pointerHub", null);
|
71
|
+
__decorate([
|
72
|
+
Lazy,
|
73
|
+
__metadata("design:type", Address),
|
74
|
+
__metadata("design:paramtypes", [])
|
75
|
+
], Field.prototype, "address", null);
|
76
|
+
__decorate([
|
77
|
+
Lazy,
|
78
|
+
__metadata("design:type", String),
|
79
|
+
__metadata("design:paramtypes", [])
|
80
|
+
], Field.prototype, "debugPath", null);
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { PointerField } from "./pointer";
|
2
|
+
import { Vertex } from "./vertex";
|
3
|
+
import { Box } from "./box";
|
4
|
+
export declare class GraphEdges {
|
5
|
+
#private;
|
6
|
+
constructor();
|
7
|
+
watchVertex(vertex: Vertex | PointerField): void;
|
8
|
+
unwatchVerticesOf(...boxes: ReadonlyArray<Box>): void;
|
9
|
+
connect(source: PointerField, target: Vertex): void;
|
10
|
+
disconnect(source: PointerField): void;
|
11
|
+
outgoingEdgesOf(box: Box): ReadonlyArray<[PointerField, Vertex]>;
|
12
|
+
incomingEdgesOf(vertex: Box | Vertex): ReadonlyArray<PointerField>;
|
13
|
+
validateRequirements(): void;
|
14
|
+
verifyPointers(): void;
|
15
|
+
}
|
16
|
+
//# sourceMappingURL=graph-edges.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"graph-edges.d.ts","sourceRoot":"","sources":["../src/graph-edges.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,YAAY,EAAC,MAAM,WAAW,CAAA;AACtC,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAA;AAEzB,qBAAa,UAAU;;;IAanB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAchD,iBAAiB,CAAC,GAAG,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,GAAG,IAAI;IAoBrD,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAQnD,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAOtC,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,aAAa,CAAC,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAIhE,eAAe,CAAC,MAAM,EAAE,GAAG,GAAG,MAAM,GAAG,aAAa,CAAC,YAAY,CAAC;IASlE,oBAAoB,IAAI,IAAI;IAqB5B,cAAc,IAAI,IAAI;CAczB"}
|
@@ -0,0 +1,109 @@
|
|
1
|
+
import { Arrays, assert, isDefined, isInstanceOf, panic } from "@opendaw/lib-std";
|
2
|
+
import { Address } from "./address";
|
3
|
+
import { PointerField } from "./pointer";
|
4
|
+
export class GraphEdges {
|
5
|
+
#requiresTarget;
|
6
|
+
#requiresPointer;
|
7
|
+
#incoming;
|
8
|
+
#outgoing;
|
9
|
+
constructor() {
|
10
|
+
this.#requiresTarget = Address.newSet(source => source.address);
|
11
|
+
this.#requiresPointer = Address.newSet(vertex => vertex.address);
|
12
|
+
this.#incoming = Address.newSet(([vertex]) => vertex.address);
|
13
|
+
this.#outgoing = Address.newSet(([source]) => source.address);
|
14
|
+
}
|
15
|
+
watchVertex(vertex) {
|
16
|
+
if (isInstanceOf(vertex, PointerField)) {
|
17
|
+
if (!vertex.mandatory) {
|
18
|
+
return panic("watchVertex called but has no edge requirement");
|
19
|
+
}
|
20
|
+
this.#requiresTarget.add(vertex);
|
21
|
+
}
|
22
|
+
else {
|
23
|
+
if (!vertex.pointerRules.mandatory) {
|
24
|
+
return panic("watchVertex called but has no edge requirement");
|
25
|
+
}
|
26
|
+
this.#requiresPointer.add(vertex);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
unwatchVerticesOf(...boxes) {
|
30
|
+
const map = ({ box: { address: { uuid } } }) => uuid;
|
31
|
+
for (const { address: { uuid } } of boxes) {
|
32
|
+
this.#removeSameBox(this.#requiresTarget, uuid, map);
|
33
|
+
this.#removeSameBox(this.#requiresPointer, uuid, map);
|
34
|
+
}
|
35
|
+
for (const box of boxes) {
|
36
|
+
const outgoingLinks = this.outgoingEdgesOf(box);
|
37
|
+
if (outgoingLinks.length > 0) {
|
38
|
+
return panic(`${box} has outgoing edges: ${outgoingLinks.map(([source, target]) => `[${source.toString()}, ${target.toString()}]`)}`);
|
39
|
+
}
|
40
|
+
const incomingPointers = this.incomingEdgesOf(box);
|
41
|
+
if (incomingPointers.length > 0) {
|
42
|
+
return panic(`${box} has incoming edges from: ${incomingPointers.map((source) => source.toString())}`);
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
connect(source, target) {
|
47
|
+
this.#outgoing.add([source, target]);
|
48
|
+
this.#incoming.opt(target.address).match({
|
49
|
+
none: () => this.#incoming.add([target, [source]]),
|
50
|
+
some: ([, sources]) => sources.push(source)
|
51
|
+
});
|
52
|
+
}
|
53
|
+
disconnect(source) {
|
54
|
+
const [, target] = this.#outgoing.removeByKey(source.address);
|
55
|
+
const [, sources] = this.#incoming.get(target.address);
|
56
|
+
Arrays.remove(sources, source);
|
57
|
+
if (sources.length === 0) {
|
58
|
+
this.#incoming.removeByKey(target.address);
|
59
|
+
}
|
60
|
+
}
|
61
|
+
outgoingEdgesOf(box) {
|
62
|
+
return this.#collectSameBox(this.#outgoing, box.address.uuid, ([{ box: { address: { uuid } } }]) => uuid);
|
63
|
+
}
|
64
|
+
incomingEdgesOf(vertex) {
|
65
|
+
if (vertex.isBox()) {
|
66
|
+
return this.#collectSameBox(this.#incoming, vertex.address.uuid, ([{ address: { uuid } }]) => uuid)
|
67
|
+
.flatMap(([_, pointers]) => pointers);
|
68
|
+
}
|
69
|
+
else {
|
70
|
+
return this.#incoming.opt(vertex.address).mapOr(([_, pointers]) => pointers, Arrays.empty());
|
71
|
+
}
|
72
|
+
}
|
73
|
+
validateRequirements() {
|
74
|
+
this.#requiresTarget.forEach(pointer => {
|
75
|
+
if (pointer.isEmpty()) {
|
76
|
+
if (pointer.mandatory) {
|
77
|
+
return panic(`Pointer ${pointer.toString()} requires an edge.`);
|
78
|
+
}
|
79
|
+
else {
|
80
|
+
return panic(`Illegal state: ${pointer} has no edge requirements.`);
|
81
|
+
}
|
82
|
+
}
|
83
|
+
});
|
84
|
+
this.#requiresPointer.forEach(target => {
|
85
|
+
if (target.pointerHub.isEmpty()) {
|
86
|
+
if (target.pointerRules.mandatory) {
|
87
|
+
return panic(`Target ${target.toString()} requires an edge.`);
|
88
|
+
}
|
89
|
+
else {
|
90
|
+
return panic(`Illegal state: ${target} has no edge requirements.`);
|
91
|
+
}
|
92
|
+
}
|
93
|
+
});
|
94
|
+
}
|
95
|
+
verifyPointers() {
|
96
|
+
this.#requiresTarget.forEach(pointer => assert(pointer.isAttached(), `${pointer.address.toString()} is not attached`));
|
97
|
+
this.#requiresPointer.forEach(pointer => assert(pointer.isAttached(), `${pointer.address.toString()} is not attached`));
|
98
|
+
}
|
99
|
+
#collectSameBox(set, id, map) {
|
100
|
+
const range = Address.boxRange(set, id, map);
|
101
|
+
return isDefined(range) ? set.values().slice(range[0], range[1]) : Arrays.empty();
|
102
|
+
}
|
103
|
+
#removeSameBox(set, id, map) {
|
104
|
+
const range = Address.boxRange(set, id, map);
|
105
|
+
if (isDefined(range)) {
|
106
|
+
set.removeRange(range[0], range[1]);
|
107
|
+
}
|
108
|
+
}
|
109
|
+
}
|
package/dist/graph.d.ts
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
import { Exec, int, Option, Procedure, Subscription, UUID } from "@opendaw/lib-std";
|
2
|
+
import { Vertex } from "./vertex";
|
3
|
+
import { Box } from "./box";
|
4
|
+
import { Address } from "./address";
|
5
|
+
import { PointerField } from "./pointer";
|
6
|
+
import { PrimitiveField, PrimitiveValues } from "./primitive";
|
7
|
+
import { Propagation } from "./dispatchers";
|
8
|
+
import { Update } from "./updates";
|
9
|
+
import { GraphEdges } from "./graph-edges";
|
10
|
+
export type BoxFactory<BoxMap> = (name: keyof BoxMap, graph: BoxGraph<BoxMap>, uuid: UUID.Format, constructor: Procedure<Box>) => Box;
|
11
|
+
export interface TransactionListener {
|
12
|
+
onBeginTransaction(): void;
|
13
|
+
onEndTransaction(): void;
|
14
|
+
}
|
15
|
+
export interface UpdateListener {
|
16
|
+
onUpdate(update: Update): void;
|
17
|
+
}
|
18
|
+
export type Dependencies = {
|
19
|
+
boxes: Iterable<Box>;
|
20
|
+
pointers: Iterable<PointerField>;
|
21
|
+
};
|
22
|
+
export declare class BoxGraph<BoxMap = any> {
|
23
|
+
#private;
|
24
|
+
constructor(boxFactory?: Option<BoxFactory<BoxMap>>);
|
25
|
+
beginTransaction(): void;
|
26
|
+
endTransaction(): void;
|
27
|
+
inTransaction(): boolean;
|
28
|
+
constructingBox(): boolean;
|
29
|
+
resolvePointers(): void;
|
30
|
+
createBox(name: keyof BoxMap, uuid: UUID.Format, constructor: Procedure<Box>): void;
|
31
|
+
stageBox<B extends Box>(box: B, constructor?: Procedure<B>): B;
|
32
|
+
subscribeTransaction(listener: TransactionListener): Subscription;
|
33
|
+
subscribeToAllUpdates(listener: UpdateListener): Subscription;
|
34
|
+
subscribeToAllUpdatesImmediate(listener: UpdateListener): Subscription;
|
35
|
+
subscribeVertexUpdates(propagation: Propagation, address: Address, procedure: Procedure<Update>): Subscription;
|
36
|
+
subscribeEndTransaction(observer: Exec): void;
|
37
|
+
unstageBox(box: Box): void;
|
38
|
+
findBox<B extends Box = Box>(uuid: UUID.Format): Option<B>;
|
39
|
+
findVertex(address: Address): Option<Vertex>;
|
40
|
+
boxes(): ReadonlyArray<Box>;
|
41
|
+
edges(): GraphEdges;
|
42
|
+
checksum(): Int8Array;
|
43
|
+
onPrimitiveValueUpdate<V extends PrimitiveValues>(field: PrimitiveField<V, any>, oldValue: V, newValue: V): void;
|
44
|
+
onPointerAddressUpdated(pointerField: PointerField, oldValue: Option<Address>, newValue: Option<Address>): void;
|
45
|
+
dependenciesOf(box: Box): Dependencies;
|
46
|
+
verifyPointers(): {
|
47
|
+
count: int;
|
48
|
+
};
|
49
|
+
debugBoxes(): void;
|
50
|
+
debugDependencies(): void;
|
51
|
+
addressToDebugPath(address: Option<Address>): Option<string>;
|
52
|
+
toArrayBuffer(): ArrayBufferLike;
|
53
|
+
fromArrayBuffer(arrayBuffer: ArrayBuffer): void;
|
54
|
+
}
|
55
|
+
//# sourceMappingURL=graph.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"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"}
|