From 9fd8fbd7b954efb861b03dab5c5f0cf2b77dceec Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Thu, 13 Feb 2025 01:25:11 +0100 Subject: [PATCH] feat(cli): wmill dev works with flows --- cli/dev.ts | 80 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 22 deletions(-) diff --git a/cli/dev.ts b/cli/dev.ts index 2da25ec4ac..2a3dfb4a7d 100644 --- a/cli/dev.ts +++ b/cli/dev.ts @@ -8,8 +8,9 @@ import { log, open, WebSocket, + yamlParseFile, } from "./deps.ts"; -import { GlobalOptions } from "./types.ts"; +import { getTypeStrFromPath, GlobalOptions } from "./types.ts"; import { ignoreF } from "./sync.ts"; import { requireLogin, resolveWorkspace } from "./context.ts"; import { @@ -19,6 +20,8 @@ import { } from "./conf.ts"; import { exts } from "./script.ts"; import { inferContentTypeFromFilePath } from "./script_common.ts"; +import { OpenFlow } from "./gen/types.gen.ts"; +import { FlowFile, replaceInlineScripts } from "./flow.ts"; const PORT = 3001; async function dev(opts: GlobalOptions & SyncOptions) { @@ -27,54 +30,87 @@ async function dev(opts: GlobalOptions & SyncOptions) { log.info("Started dev mode"); const conf = await readConfigFile(); - let currentLastEdit: LastEdit | undefined = undefined; + let currentLastEdit: LastEditScript | LastEditFlow | undefined = undefined; const watcher = Deno.watchFs("."); const base = await Deno.realPath("."); opts = await mergeConfigWithConfigFile(opts); const ignore = await ignoreF(opts); + const changesTimeouts: Record = {}; async function watchChanges() { for await (const event of watcher) { - log.debug(">>>> event", event); - // Example event: { kind: "create", paths: [ "/home/alice/deno/foo.txt" ] } - await loadPaths(event.paths); + // console.log(">>>> event", event); + const key = event.paths.join(","); + if (changesTimeouts[key]) { + clearTimeout(changesTimeouts[key]); + } + changesTimeouts[key] = setTimeout(async () => { + delete changesTimeouts[key]; + await loadPaths(event.paths); + }, 100); } } + const DOT_FLOW_SEP = ".flow" + SEP; async function loadPaths(pathsToLoad: string[]) { - const paths = pathsToLoad.filter((path) => - exts.some((ext) => path.endsWith(ext)) + const paths = pathsToLoad.filter( + (path) => + exts.some((ext) => path.endsWith(ext)) || path.includes(DOT_FLOW_SEP) ); if (paths.length == 0) { return; } const cpath = (await Deno.realPath(paths[0])).replace(base + SEP, ""); - console.log("Detected change in " + cpath); if (!ignore(cpath, false)) { - const content = await Deno.readTextFile(cpath); - const splitted = cpath.split("."); - const wmPath = splitted[0]; - const lang = inferContentTypeFromFilePath(cpath, conf.defaultTs); - currentLastEdit = { - content, - path: wmPath, - language: lang, - }; - broadcastChanges(currentLastEdit); - log.info("Updated " + wmPath); + const typ = getTypeStrFromPath(cpath); + log.info("Detected change in " + cpath + " (" + typ + ")"); + if (typ == "flow") { + const localPath = cpath.split(DOT_FLOW_SEP)[0] + DOT_FLOW_SEP; + const localFlow = (await yamlParseFile( + localPath + "flow.yaml" + )) as FlowFile; + replaceInlineScripts(localFlow.value.modules, localPath, undefined); + currentLastEdit = { + type: "flow", + flow: localFlow, + uriPath: localPath, + }; + log.info("Updated " + localPath); + broadcastChanges(currentLastEdit); + } else if (typ == "script") { + const content = await Deno.readTextFile(cpath); + const splitted = cpath.split("."); + const wmPath = splitted[0]; + const lang = inferContentTypeFromFilePath(cpath, conf.defaultTs); + currentLastEdit = { + type: "script", + content, + path: wmPath, + language: lang, + }; + log.info("Updated " + wmPath); + broadcastChanges(currentLastEdit); + } } } - type LastEdit = { + type LastEditScript = { + type: "script"; content: string; path: string; language: string; }; + type LastEditFlow = { + type: "flow"; + flow: OpenFlow; + uriPath: string; + }; + const connectedClients: Set = new Set(); // Function to send a message to all connected clients - function broadcastChanges(lastEdit: LastEdit) { + function broadcastChanges(lastEdit: LastEditScript | LastEditFlow) { for (const client of connectedClients.values()) { client.send(JSON.stringify(lastEdit)); } @@ -119,7 +155,7 @@ async function dev(opts: GlobalOptions & SyncOptions) { // Start the server const port = await getPort.default({ port: 3001 }); const url = - `${workspace.remote}scripts/dev?workspace=${workspace.workspaceId}&local=true` + + `${workspace.remote}dev?workspace=${workspace.workspaceId}&local=true&wm_token=${workspace.token}` + (port === PORT ? "" : `&port=${port}`); console.log(`Go to ${url}`);