diff --git a/cli/context.ts b/cli/context.ts index fc092cd66d..5e544851f3 100644 --- a/cli/context.ts +++ b/cli/context.ts @@ -23,7 +23,7 @@ async function tryResolveWorkspace( { isError: false; value: Workspace } | { isError: true; error: string } > { const cache = (opts as any).__secret_workspace; - if (cache) return cache; + if (cache) return { isError: false, value: cache }; if (opts.workspace) { const e = await getWorkspaceByName(opts.workspace); @@ -53,7 +53,6 @@ export async function resolveWorkspace( ): Promise { const res = await tryResolveWorkspace(opts); if (res.isError) { - console.log(res.error); return Deno.exit(-1); } else { return res.value; @@ -62,8 +61,8 @@ export async function resolveWorkspace( export async function requireLogin(opts: GlobalOptions): Promise { const workspace = await resolveWorkspace(opts); - let token = await tryGetLoginInfo(opts); + if (!token) { token = workspace.token; } @@ -80,9 +79,9 @@ export async function requireLogin(opts: GlobalOptions): Promise if (!newToken) { throw new Error("Could not reauth"); } - removeWorkspace(workspace.name); + removeWorkspace(workspace.name, false, opts); workspace.token = newToken; - addWorkspace(workspace); + addWorkspace(workspace, opts); setClient( token, diff --git a/cli/flow.ts b/cli/flow.ts index 7e5ad8e9b9..ca4a2661ec 100644 --- a/cli/flow.ts +++ b/cli/flow.ts @@ -192,7 +192,7 @@ async function list(opts: GlobalOptions & { showArchived?: boolean }) { } async function run( opts: GlobalOptions & { - input: string[]; + data?: string; silent: boolean; }, path: string, @@ -200,7 +200,8 @@ async function run( const workspace = await resolveWorkspace(opts); await requireLogin(opts); - const input = await resolve(opts.input); + const input = opts.data ? await resolve(opts.data) : {}; + const id = await JobService.runFlowByPath({ workspace: workspace.workspaceId, @@ -236,6 +237,7 @@ async function run( if (!opts.silent) { console.log(colors.green.underline.bold("Flow ran to completion")); + console.log() } const jobInfo = await JobService.getCompletedJob({ workspace: workspace.workspaceId, @@ -257,8 +259,8 @@ const command = new Command() .command("run", "run a flow by path.") .arguments("") .option( - "-i --input [inputs...:string]", - "Inputs specified as JSON objects or simply as =. Supports file inputs using @ and stdin using @- these also need to be formatted as JSON. Later inputs override earlier ones.", + "-d --data ", + "Inputs specified as a JSON string or a file using @ or stdin using @-.", ) .option( "-s --silent", diff --git a/cli/script.ts b/cli/script.ts index 6d66be0891..fc0bf22ac0 100644 --- a/cli/script.ts +++ b/cli/script.ts @@ -11,6 +11,7 @@ import { Table, } from "./deps.ts"; import { Any, array, decoverto, model, property } from "./decoverto.ts"; +import { writeAllSync } from "https://deno.land/std@0.176.0/streams/mod.ts"; @model() export class ScriptFile { @@ -280,50 +281,27 @@ async function list(opts: GlobalOptions & { showArchived?: boolean }) { .render(); } -export async function resolve(inputs: string[]): Promise> { - let result = {}; - - if (!inputs) { - return result; +export async function resolve(input: string): Promise> { + if (!input) { + throw new Error("No data given"); } - for (const input of inputs) { - let data: string; - if (input.startsWith("@")) { - if (input == "@-") { - data = new TextDecoder().decode(await readAll(Deno.stdin)); - } else { - data = await Deno.readTextFile(input.substring(1)); - } - } else { - if (input.startsWith("{")) { - data = input; - } else { - const key = input.split("=", 1)[0]; - const value = input.substring(key.length + 1); - let o; - try { - o = JSON.parse(value); - } catch { - o = value; - } - data = JSON.stringify(Object.fromEntries([[key, o]])); - } - } - let jsonObj; - try { - jsonObj = JSON.parse(data); - } catch { - jsonObj = data; - } - result = { ...result, ...jsonObj }; + if (input == "@-") { + input = new TextDecoder().decode(await readAll(Deno.stdin)); + } if (input[0] == "@") { + input = await Deno.readTextFile(input.substring(1)); + } + try { + return JSON.parse(input); + } catch (e) { + console.error("Impossible to parse input as JSON", input) + throw e } - return result; } async function run( opts: GlobalOptions & { - input: string[]; + data?: string; silent: boolean; }, path: string, @@ -331,7 +309,8 @@ async function run( const workspace = await resolveWorkspace(opts); await requireLogin(opts); - const input = await resolve(opts.input); + + const input = opts.data ? await resolve(opts.data) : {}; const id = await JobService.runScriptByPath({ workspace: workspace.workspaceId, path, @@ -364,7 +343,9 @@ export async function track_job(workspace: string, id: string) { const result = await JobService.getCompletedJob({ workspace, id }); console.log(result.logs); + console.log() console.log(colors.bold.underline.green("Job Completed")); + console.log() return; } catch { /* ignore */ @@ -403,7 +384,7 @@ export async function track_job(workspace: string, id: string) { } if (updates.new_logs) { - console.log(updates.new_logs); + writeAllSync(Deno.stdout, new TextEncoder().encode(updates.new_logs)); logOffset += updates.new_logs.length; } @@ -426,12 +407,15 @@ export async function track_job(workspace: string, id: string) { if ((final_job.logs?.length ?? -1) > logOffset) { console.log(final_job.logs!.substring(logOffset)); } - + console.log("\n") if (final_job.success) { console.log(colors.bold.underline.green("Job Completed")); + } else { console.log(colors.bold.underline.red("Job Completed")); } + console.log() + } catch { console.log("Job appears to have completed, but no data can be retrieved"); } @@ -466,8 +450,8 @@ const command = new Command() .command("run", "run a script by path") .arguments("") .option( - "-i --input [inputs...:string]", - "Inputs specified as JSON objects or simply as =. Supports file inputs using @ and stdin using @- these also need to be formatted as JSON. Later inputs override earlier ones.", + "-d --data ", + "Inputs specified as a JSON string or a file using @ or stdin using @-.", ) .option( "-s --silent", diff --git a/cli/workspace.ts b/cli/workspace.ts index 87e31a488e..7919f14b49 100644 --- a/cli/workspace.ts +++ b/cli/workspace.ts @@ -9,9 +9,11 @@ import { Input, setClient, Table, + UserService, WorkspaceService, } from "./deps.ts"; import { decoverto, model, property } from "./decoverto.ts"; +import { requireLogin } from "./context.ts"; @model() export class Workspace { @@ -308,6 +310,11 @@ async function remove(_opts: GlobalOptions, name: string) { await removeWorkspace(name, false, _opts); } +async function whoami(_opts: GlobalOptions) { + await requireLogin(_opts) + console.log(await UserService.globalWhoami()) +} + const command = new Command() .description("workspace related commands") .action(list as any) @@ -335,6 +342,9 @@ const command = new Command() .command("remove") .description("Remove a workspace") .arguments("") - .action(remove as any); + .action(remove as any) + .command("whoami") + .description("Show the currently active user") + .action(whoami as any); export default command; diff --git a/frontend/src/lib/components/FlowBuilder.svelte b/frontend/src/lib/components/FlowBuilder.svelte index 4b6f5bb7fc..e38a685d3f 100644 --- a/frontend/src/lib/components/FlowBuilder.svelte +++ b/frontend/src/lib/components/FlowBuilder.svelte @@ -113,7 +113,6 @@ await createSchedule(flow.path) } } - sendUserToast(`Flow saved at ${$flowStore.path}`) goto(`/flows/get/${$flowStore.path}?workspace_id=${$workspaceStore}`) } diff --git a/frontend/src/lib/components/ModulePreview.svelte b/frontend/src/lib/components/ModulePreview.svelte index 17b4f37334..02f90e8a6c 100644 --- a/frontend/src/lib/components/ModulePreview.svelte +++ b/frontend/src/lib/components/ModulePreview.svelte @@ -86,6 +86,7 @@ detailed={false} topButton bind:args={stepArgs} + isFlow={false} /> {#if testIsLoading}