Skip to content

Commit 8921b6e

Browse files
committed
callable nodes now default for functions (by proxy) else specified
1 parent 78841b5 commit 8921b6e

File tree

3 files changed

+50
-20
lines changed

3 files changed

+50
-20
lines changed

examples/basics/graph/index.ts

+16-9
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ let roots = {
3838
__operator:'multiply',
3939
__args:['__input',5] //structure inputs for the operator on this level, '__input' or '__output' will place the input argument here
4040
} as GraphNodeProperties
41-
}
41+
},
4242
} as GraphNodeProperties,
4343

4444
verboseGraphSequence:{ //same as graphSequence using functions
@@ -52,7 +52,8 @@ let roots = {
5252
},
5353
__args:['__input',5]
5454
}
55-
}
55+
},
56+
__callable:true
5657
} as GraphNodeProperties,
5758

5859
//let's make a node that listens to the output of other nodes
@@ -77,8 +78,6 @@ console.log('Graph instance:', graph);
7778

7879

7980

80-
81-
8281
let args = [1,2,3,4,5];
8382

8483
let result1 = new Promise((res) => {
@@ -92,28 +91,36 @@ graph.run('graphSequence', ...args);
9291

9392

9493

94+
9595
let result3 = graph.run('nodeSyntax', ...args);
9696
let result2 = graph.run('nativeJSSyntax', ...args);
97-
let node = graph.get('nodeSyntax');
98-
let result4 = node(...args); //nodes are now callable.
9997
//lets remove a node and then try to run it on the graph again
10098
let removed = graph.remove('nativeJSSyntax');
10199
let result_undefined = graph.run('nativeJSSyntax', ...args);
102100
console.log('result after removal should be undefined:', result_undefined);
103101

104102

103+
let node = graph.get('verboseGraphSequence');
104+
105+
let result4 = new Promise((res) => {
106+
let sub = graph.subscribe('verboseGraphSequence.result', (output)=>{
107+
graph.unsubscribe('verboseGraphSequence.result', sub);
108+
res(output);
109+
});
110+
});
105111

112+
node(...args); //this sequences is callable
106113

107114

108-
result1.then((result) => {
115+
Promise.all([result1,result4]).then((results) => {
109116
document.body.insertAdjacentHTML('afterbegin', `
110117
<div>
111118
Node Run Results should match:
112119
<div style='margin-left:10px'>
113120
Graph Node Syntax: ${result3}<br/>
114121
Native JS Syntax: ${result2}<br/>
115-
Graph Sequence Syntax: ${result}<br/>
116-
Callable Syntax: ${result4}<br/>
122+
Graph Sequence Syntax: ${results[0]}<br/>
123+
Callable Syntax: ${results[1]}<br/>
117124
</div>
118125
</div>
119126
`);

src/core/Graph.ts

+33-10
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export type GraphNodeProperties = {
1919
[key:string]:any
2020
},
2121
__args?:any[], //can structure input arguments, include '__result' when generically calling operators for where to pass the original input in in a set of arguments
22+
__callable?:boolean, //we can have the graphnode return itself as a callable function with private properties
2223
[key:string]:any
2324
}
2425

@@ -85,9 +86,8 @@ export class Callable extends Function {
8586

8687
}
8788

88-
8989
//this is a scope
90-
export class GraphNode extends Callable {
90+
export class GraphNode {
9191

9292
__node:{
9393
tag:string,
@@ -114,9 +114,35 @@ export class GraphNode extends Callable {
114114
[key:string]:any
115115

116116
//pass GraphNodeProperties, functions, or tags of other nodes
117-
constructor(properties:any, parent?:{[key:string]:any}, graph?:Graph) {
118-
super();
117+
constructor(properties:GraphNodeProperties, parent?:{[key:string]:any}, graph?:Graph) {
118+
//super();
119119
this.__setProperties(properties,parent,graph);
120+
121+
// Check if the properties are a function or denote the GraphNode to be callable (but all properties private!!)
122+
if (typeof properties === 'function' || properties.__callable) { //assuming operator is defined
123+
const callableInstance = new Callable();
124+
callableInstance.__call = (...args) => this.__operator(...args);
125+
126+
// Create a proxy to delegate function calls to callableInstance and properties to this
127+
const proxy = new Proxy(callableInstance, { //experimental
128+
get: (target, prop, receiver) => {
129+
if (Reflect.has(this, prop)) {
130+
return Reflect.get(this, prop, receiver);
131+
}
132+
return Reflect.get(target, prop, receiver);
133+
},
134+
set: (target, prop, value, receiver) => {
135+
if (Reflect.has(this, prop)) {
136+
return Reflect.set(this, prop, value, receiver);
137+
}
138+
return Reflect.set(target, prop, value, receiver);
139+
}
140+
});
141+
Object.setPrototypeOf(proxy,this); //pass instanceof checks
142+
143+
//@ts-ignore
144+
return proxy;
145+
}
120146
}
121147

122148
__setProperties = (properties, parent, graph) => {
@@ -345,7 +371,7 @@ export class GraphNode extends Callable {
345371
let sub;
346372

347373
let k = subInput ? this.__node.unique+'.'+key+'input' : this.__node.unique+'.'+key;
348-
if(typeof callback === 'function' && !(callback as GraphNode)?.__node)
374+
if(typeof callback === 'function' && !(callback as any)?.__node)
349375
sub = subscribeToFunction(k, (callback, target) => (target ? target : callback), callback as (...res:any)=>void)
350376
else if((callback as GraphNode)?.__node) sub = subscribeToFunction(k,
351377
(callback, target) => (target ? target : (callback as GraphNode).__node.unique),
@@ -369,7 +395,7 @@ export class GraphNode extends Callable {
369395

370396
let k = subInput ? this.__node.unique+'input' : this.__node.unique;
371397

372-
if(typeof callback === 'function' && !(callback as GraphNode)?.__node) sub = subscribeToFunction(k, (callback, target) => (target ? target : callback), callback as (...res:any)=>void)
398+
if(typeof callback === 'function' && !(callback as any)?.__node) sub = subscribeToFunction(k, (callback, target) => (target ? target : callback), callback as (...res:any)=>void)
373399
else if((callback as GraphNode)?.__node) {
374400
sub = subscribeToFunction(k,
375401
(callback, target) => target ? target : (callback as GraphNode).__node.unique,
@@ -421,8 +447,6 @@ export class GraphNode extends Callable {
421447
}
422448
}
423449

424-
this.__call = ((...args) => { return this.__operator(...args); });
425-
426450
return this.__operator;
427451
}
428452

@@ -1282,7 +1306,7 @@ export class Graph {
12821306
}
12831307
} else {
12841308
if(typeof onEvent === 'string') onEvent = this.__node.nodes.get(onEvent).__operator;
1285-
if(typeof onEvent === 'function' && !(onEvent as GraphNode)?.__node) sub = this.__node.state.subscribeEvent(nodeEvent, onEvent as (...res:any)=>void);
1309+
if(typeof onEvent === 'function' && !(onEvent as any)?.__node) sub = this.__node.state.subscribeEvent(nodeEvent, onEvent as (...res:any)=>void);
12861310
}
12871311
}
12881312
return sub;
@@ -1462,7 +1486,6 @@ let objProps = Object.getOwnPropertyNames(Object.getPrototypeOf({}));
14621486

14631487

14641488

1465-
14661489

14671490
// class AnotherCallable extends Callable {
14681491
// constructor() {

src/services/worker/WorkerCanvas.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//provide routes for applying canvases to workers
2-
import { GraphNode } from '../../core/Graph';
2+
33
import { proxyElementWorkerRoutes, initProxyElement } from './ProxyListener';
44

55
declare var WorkerGlobalScope;

0 commit comments

Comments
 (0)