feat: install and load packages from noflo-browser

This commit is contained in:
lin onetwo 2023-07-11 00:56:25 +08:00
parent aa9edcb433
commit 1ace9b331f
9 changed files with 761 additions and 104 deletions

View file

@ -63,14 +63,34 @@
"menubar": "9.3.0",
"nanoid": "^4.0.2",
"node-fetch": "3.3.1",
"noflo-adapters": "^0.3.2",
"noflo-ajax": "^0.3.0",
"noflo-assembly": "^0.3.1",
"noflo-assembly-utils": "^0.2.1",
"noflo-clmtrackr": "^0.3.0",
"noflo-core": "^0.6.1",
"noflo-css": "^0.2.0",
"noflo-dom": "^0.3.0",
"noflo-filesystem": "^2.2.0",
"noflo-flow": "^0.8.0",
"noflo-geometry": "^0.3.0",
"noflo-graph": "^0.4.0",
"noflo-groups": "^0.3.0",
"noflo-gum": "^0.4.0",
"noflo-image": "^0.4.0",
"noflo-indexeddb": "^0.3.1",
"noflo-interaction": "^0.3.1",
"noflo-localstorage": "^0.3.0",
"noflo-math": "^0.4.0",
"noflo-nodejs": "^0.15.2",
"noflo-objects": "^0.7.0",
"noflo-packets": "^0.3.0",
"noflo-physics": "^0.3.0",
"noflo-routers": "^0.5.0",
"noflo-strings": "^0.5.1",
"noflo-tween": "^0.3.0",
"noflo-webaudio": "^0.4.0",
"noflo-websocket": "^0.4.0",
"reflect-metadata": "0.1.13",
"registry-js": "1.15.1",
"rxjs": "7.8.1",
@ -168,6 +188,7 @@
"node-polyfill-webpack-plugin": "^2.0.1",
"noflo": "^1.4.3",
"noflo-component-loader": "^0.4.1",
"path-browserify": "^1.0.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-helmet": "6.1.0",

725
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,5 +0,0 @@
# In the graph we first need to define the nodes and the connections between them
Read(filesystem/ReadFile) OUT -> IN Display(core/Output)
# Start off the graph by sending a filename to the file reader
'package.json' -> IN Read

View file

@ -1,7 +1,6 @@
import { sidebarWidth } from '@/constants/style';
import type { Graph } from 'fbp-graph';
import { ComponentLoader } from 'noflo';
import components from 'noflo/lib/loader/register';
import styled from 'styled-components';
import TheGraph from 'the-graph';
import type { IFBPLibrary, ITheGraphProps } from 'the-graph';
@ -110,32 +109,8 @@ export function GraphEditor(props: Partial<ITheGraphProps> & IGraphEditorProps)
library,
appReference,
});
const buildInitialLibrary = useCallback((graph: Graph) => {
const components = TheGraph.library.componentsFromGraph(graph);
components.forEach((component) => {
registerComponent(component, true);
});
}, [registerComponent]);
const { addMenu, addMenuCallback, addMenuAction, getMenuDef } = useMenu();
// when ready
useEffect(() => {
// initializeAutolayouter();
buildInitialLibrary(graph);
}, [buildInitialLibrary]);
useEffect(() => {
void (async function IIFE() {
const loader = new ComponentLoader('');
const componentList = await loader.listComponents();
// DEBUG: console componentList
// DEBUG: console components
console.log(`components`, components.getSource(loader, 'BaseName', console.log));
console.log(`componentList`, componentList);
})();
}, []);
// Attach nav
function fitGraphInView() {
// editor.triggerFit();
@ -143,6 +118,9 @@ export function GraphEditor(props: Partial<ITheGraphProps> & IGraphEditorProps)
function panEditorTo() {}
// DEBUG: console library
console.log(`library`, library);
return (
<Container className={`the-graph-${theme}`}>
<TheGraph.App

View file

@ -1,12 +1,12 @@
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
/* eslint-disable @typescript-eslint/promise-function-async */
import { useThemeObservable } from '@services/theme/hooks';
import { Graph } from 'fbp-graph';
import { type Graph, loadJSON } from 'fbp-graph/lib/Graph';
import { ComponentLoader } from 'noflo';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import type { IFBPLibrary } from 'the-graph';
import { GraphEditor } from './GraphEditor';
import { loadGraphJSON } from './loadGraph';
import { photoboothJSON } from './photobooth.json';
export default function Workflow(): JSX.Element {
@ -16,12 +16,29 @@ export default function Workflow(): JSX.Element {
const [library, setLibrary] = useState<IFBPLibrary | undefined>();
const [graph, setGraph] = useState<Graph | undefined>();
useEffect(() => {
void loadGraphJSON(photoboothJSON).then(([graph, library]) => {
setLibrary(library);
void loadJSON(photoboothJSON).then(graph => {
setGraph(graph);
});
}, []);
return graph
// load library bundled by webpack noflo-component-loader from installed noflo related npm packages
useEffect(() => {
const loader = new ComponentLoader('');
void loader.listComponents().then((componentList) => {
const libraryToLoad: IFBPLibrary = {};
Object.entries(componentList).forEach(([name, componentDefinitionRaw]) => {
if (typeof componentDefinitionRaw === 'string') {
// TODO: handle these ComponentDefinition types
return;
}
if ('getComponent' in componentDefinitionRaw) {
const componentDefinition = componentDefinitionRaw.getComponent();
libraryToLoad[name] = componentDefinition;
}
});
setLibrary(libraryToLoad);
});
}, []);
return graph && library
? (
<>
<GraphEditor theme={theme?.shouldUseDarkColors ? 'dark' : 'light'} library={library} graph={graph} />

View file

@ -1,19 +0,0 @@
import { type Graph, loadJSON } from 'fbp-graph/lib/Graph';
import { mapValues, sample } from 'lodash';
import TheGraph from 'the-graph';
import { IFbpGraphJSON } from './fbpGraphJSON.type';
export async function loadGraphJSON(graphData: IFbpGraphJSON): Promise<[Graph, TheGraph.IFBPLibrary]> {
const graph = await loadJSON(JSON.stringify(graphData));
const library = TheGraph.library.libraryFromGraph(graph);
// DEBUG: console library
console.log(`library`, library);
return [
graph,
mapValues(library, component => {
component.icon = sample(Object.keys(TheGraph.FONT_AWESOME));
return component;
}),
];
}

View file

@ -1,7 +1,8 @@
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
import type { Graph } from 'fbp-graph';
import { RefObject, useCallback, useState } from 'react';
import TheGraph, { IFBPComponent } from 'the-graph';
import TheGraph from 'the-graph';
import type { Component } from 'noflo';
const unnamespace = (name: string) => {
if (!name.includes('/')) {
@ -116,11 +117,11 @@ export function useMouseEvents({ graph, library, appReference }: { appReference:
appReference.current.focusNode(node);
};
const getComponent = (name: string): IFBPComponent | undefined => {
const getComponent = (name: string): Component | undefined => {
return library?.[name];
};
const registerComponent = (definition: TheGraph.IFBPComponent, generated: boolean) => {
const registerComponent = (definition: Component, generated: boolean) => {
const component = getComponent(definition.name);
if (component && generated) {
return;

29
src/type.d.ts vendored
View file

@ -10,7 +10,8 @@ declare module '@tiddlygit/tiddlywiki' {
}
declare module 'the-graph' {
import type { Graph } from 'fbp-graph';
import { Graph } from 'fbp-graph';
import { Component } from 'noflo';
export interface ITheGraphProps {
getMenuDef?: (options: {
@ -34,16 +35,22 @@ declare module 'the-graph' {
name: string;
type: string;
}
export interface IFBPComponent {
description: string;
icon: string;
inports: ITheGraphNodePort[];
name: string;
outports: ITheGraphNodePort[];
unnamespaced?: boolean;
}
function componentsFromGraph(graph: Graph): IFBPComponent[];
export type IFBPLibrary = Record<string, IFBPComponent>;
function componentsFromGraph(graph: Graph): Component[];
/**
* value Component is actually:
*
* ```ts
* export interface IFBPComponent {
* description: string;
* icon: string;
* inports: ITheGraphNodePort[];
* name: string;
* outports: ITheGraphNodePort[];
* unnamespaced?: boolean;
* }
* ```
*/
export type IFBPLibrary = Record<string, Component>;
function libraryFromGraph(graph: Graph): IFBPLibrary;
export const library = {

View file

@ -15,7 +15,7 @@ module.exports = {
resolve: {
alias: webpackAlias,
extensions: ['.js', '.ts', '.jsx', '.tsx', '.css'],
fallback: { crypto: false, fs: false, process: false },
fallback: { crypto: false, fs: false, process: false, "path": require.resolve("path-browserify") },
},
output: {
chunkFilename: 'main_window/[name].chunk.js',