You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

107 lines
3.1 KiB

import {Cell} from '@antv/x6';
import tpl from './template/runOnline';
import simplifyDSL from './simplifyDSL';
interface DSL {
cells: Cell.Properties[];
}
/**
* Solution
*
* 1. find the source node form dsl, and if it is not imove-start,
* then insert a vitural imove-start at first.
*
* 2. transform node funciton, follows should be noted:
* - import statement should be replaced with import('packge/from/network')
* - export statement should be replace with return function
* - each node function should be wrapped within a new function to avoid duplicate declaration global variable
*
* 3. assemble Logic, Context, simplyfied dsl and nodeFns map into one file
*
*/
const INSERT_DSL_COMMENT = '// define dsl here';
const INSERT_NODE_FNS_COMMENT = '// define nodeFns here';
const importRegex = /import\s+([\s\S]*?)\s+from\s+(?:('[@\.\/\-\w]+')|("[@\.\/\-\w]+"))\s*;?/mg;
const virtualSourceNode = {
id: 'virtual-imove-start',
shape: 'imove-start',
data: {
trigger: 'virtual-imove-start',
configData: {},
code: 'export default async function(ctx) {\n \n}'
}
};
const findStartNode = (dsl: DSL): Cell.Properties => {
const nodes = dsl.cells.filter(cell => cell.shape !== 'edge');
const edges = dsl.cells.filter(cell => cell.shape === 'edge');
if(nodes.length === 0) {
throw new Error('Compile failed, no node is selected');
}
let foundEdge = null;
let startNode = nodes[0];
while(foundEdge = edges.find(edge => edge.target.cell === startNode.id)) {
const newSourceId = foundEdge.source.cell;
startNode = nodes.find(node => node.id === newSourceId) as Cell.Properties;
}
if(startNode.shape !== 'imove-start') {
dsl.cells.push(
virtualSourceNode,
{
shape: "edge",
source: {
cell: 'virtual-imove-start',
},
target: {
cell: startNode.id
}
}
);
startNode = virtualSourceNode;
}
return startNode;
};
const compileSimplifiedDSL = (dsl: DSL): string => {
const simplyfiedDSL = JSON.stringify(simplifyDSL(dsl), null, 2);
return `const dsl = ${simplyfiedDSL};`;
};
const compileNodeFn = (node: Cell.Properties): string => {
const {data: {label, code}} = node;
const newCode = code.replace(importRegex, (match: string, p1: string, p2: string, p3: string) => {
const pkgName = (p2 || p3).replace(/('|")/g, '');
return `const ${p1} = (await import('https://jspm.dev/${pkgName}')).default;`;
}).replace(/export\s+default/, 'return');
return `await (async function() {
${newCode}
}())`;
};
const compileNodeFnsMap = (dsl: DSL): string => {
const nodes = dsl.cells.filter(cell => cell.shape !== 'edge');
const kvs = nodes.map(node => {
const {id} = node;
return `'${id}': ${compileNodeFn(node)}`;
});
return `const nodeFns = {\n ${kvs.join(',\n ')}\n}`;
};
const compile = (dsl: DSL): string => {
const startNode = findStartNode(dsl);
return tpl
.replace(INSERT_DSL_COMMENT, compileSimplifiedDSL(dsl))
.replace(INSERT_NODE_FNS_COMMENT, compileNodeFnsMap(dsl))
.replace('$TRIGGER$', startNode.data.trigger);
};
export default compile;