diff --git a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts
index 1d5d8f415f..21a5009a95 100644
--- a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts
+++ b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.test.ts
@@ -47,6 +47,49 @@ describe('buildAppGraph', () => {
]);
expect([...graph.rootNodes.keys()]).toEqual(['a', 'b', 'c']);
expect([...graph.orphanNodes.keys()]).toEqual(['dx1']);
+
+ expect(JSON.parse(JSON.stringify([...graph.rootNodes.values()])))
+ .toMatchInlineSnapshot(`
+ [
+ {
+ "id": "a",
+ },
+ {
+ "attachments": {
+ "x": [
+ {
+ "id": "bx1",
+ },
+ {
+ "id": "bx2",
+ },
+ ],
+ "y": [
+ {
+ "id": "by1",
+ },
+ ],
+ },
+ "id": "b",
+ },
+ {
+ "id": "c",
+ },
+ ]
+ `);
+ expect(String(graph.rootNodes.get('a'))).toMatchInlineSnapshot(`""`);
+ expect(String(graph.rootNodes.get('b'))).toMatchInlineSnapshot(`
+ "
+ x [
+
+
+ ]
+ y [
+
+ ]
+ "
+ `);
+ expect(String(graph.rootNodes.get('c'))).toMatchInlineSnapshot(`""`);
});
it('should create a graph out of order', () => {
@@ -61,6 +104,20 @@ describe('buildAppGraph', () => {
]);
expect([...graph.rootNodes.keys()]).toEqual(['a', 'b', 'c']);
expect([...graph.orphanNodes.keys()]).toEqual(['dx1']);
+
+ expect(String(graph.rootNodes.get('a'))).toMatchInlineSnapshot(`""`);
+ expect(String(graph.rootNodes.get('b'))).toMatchInlineSnapshot(`
+ "
+ x [
+
+
+ ]
+ y [
+
+ ]
+ "
+ `);
+ expect(String(graph.rootNodes.get('c'))).toMatchInlineSnapshot(`""`);
});
it('throws an error when duplicated extensions are detected', () => {
diff --git a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts
index 9cfb430bcb..79977f6993 100644
--- a/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts
+++ b/packages/frontend-app-api/src/wiring/graph/buildAppGraph.ts
@@ -14,14 +14,71 @@
* limitations under the License.
*/
-import { AppNode, AppNodeEdges, AppNodeSpec, Mutable } from './types';
+import {
+ AppGraph,
+ AppNode,
+ AppNodeEdges,
+ AppNodeInstance,
+ AppNodeSpec,
+ Mutable,
+} from './types';
+
+function indent(str: string) {
+ return str.replace(/^/gm, ' ');
+}
+
+/** @internal */
+class SerializableAppNode implements AppNode {
+ public readonly spec: AppNodeSpec;
+ public readonly edges: AppNodeEdges = { attachments: new Map() };
+ public readonly instance?: AppNodeInstance;
+
+ constructor(spec: AppNodeSpec) {
+ this.spec = spec;
+ }
+
+ toJSON() {
+ const dataRefs = this.instance && [...this.instance.getDataRefs()];
+ return {
+ id: this.spec.id,
+ output:
+ dataRefs && dataRefs.length > 0
+ ? dataRefs.map(ref => ref.id)
+ : undefined,
+ attachments:
+ this.edges.attachments.size > 0
+ ? Object.fromEntries(this.edges.attachments)
+ : undefined,
+ };
+ }
+
+ toString() {
+ const dataRefs = this.instance && [...this.instance.getDataRefs()];
+ const out =
+ dataRefs && dataRefs.length > 0
+ ? ` out=[${[...dataRefs.keys()].join(', ')}]`
+ : '';
+
+ if (this.edges.attachments.size === 0) {
+ return `<${this.spec.id}${out} />`;
+ }
+
+ return [
+ `<${this.spec.id}${out}>`,
+ ...[...this.edges.attachments.entries()].map(([k, v]) =>
+ indent([`${k} [`, ...v.map(e => indent(e.toString())), `]`].join('\n')),
+ ),
+ `${this.spec.id}>`,
+ ].join('\n');
+ }
+}
/**
* Build the app graph by iterating through all node specs and constructing the app
* tree with all attachments in the same order as they appear in the input specs array.
* @internal
*/
-export function buildAppGraph(specs: AppNodeSpec[]) {
+export function buildAppGraph(specs: AppNodeSpec[]): AppGraph {
const nodes = new Map();
const rootNodes = new Map();
// While iterating through the inputs specs we keep track of all nodes that were created
@@ -39,12 +96,7 @@ export function buildAppGraph(specs: AppNodeSpec[]) {
throw new Error(`Unexpected duplicate extension id '${spec.id}'`);
}
- const node: AppNode = {
- spec,
- edges: {
- attachments: new Map(),
- },
- };
+ const node = new SerializableAppNode(spec);
nodes.set(spec.id, node);
if (spec.attachTo) {
diff --git a/packages/frontend-app-api/src/wiring/graph/types.ts b/packages/frontend-app-api/src/wiring/graph/types.ts
index 88fc363d6f..29c0028d66 100644
--- a/packages/frontend-app-api/src/wiring/graph/types.ts
+++ b/packages/frontend-app-api/src/wiring/graph/types.ts
@@ -52,7 +52,7 @@ export interface AppNodeEdges {
* @public
*/
export interface AppNodeInstance {
- getDataRefs(): ExtensionDataRef[];
+ getDataRefs(): Iterable>;
getData(ref: ExtensionDataRef): T | unknown;
}
@@ -71,4 +71,5 @@ export interface AppNode {
export interface AppGraph {
rootNodes: Map;
+ orphanNodes: Map;
}