Files
windmill/cli/context.ts
T
Kai Jellinghaus fc494fbf7f feat(cli): 2-Way sync (#1071)
* Export file type from each file

* Fix example scripts

* Strongly type CLI files

* Allow bash files

* Update API version

* Remove useless files

* WIP: Diff based push

* Fixup other code

* Implement Flow diffing

* Implement resource type

* Remaining impls

* WIP

* Fix missing file error

* Fix misstyping

* Improve error message

* Fix type inferrence

* Allow REMOVE everywhere

* Fix empty changeset

* Fix error message

* Fix type inferrence 2

* Fix variable diffs

* Fix include checks

* Move push & pull

* Handle script in sync

* Handle scripts

* Allow multi-path creation

* Fix merge conflicts

* Fix #1173

* Update Dependencies

* Add missing await

* Apply review comments

* Fix diff

---------

Co-authored-by: Ruben Fiszel <ruben@rubenfiszel.com>
2023-02-03 19:49:46 +01:00

147 lines
3.6 KiB
TypeScript

// deno-lint-ignore-file no-explicit-any
import { colors, setClient, UserService } from "./deps.ts";
import { loginInteractive, tryGetLoginInfo } from "./login.ts";
import { GlobalOptions } from "./types.ts";
import {
addWorkspace,
getActiveWorkspace,
getWorkspaceByName,
removeWorkspace,
Workspace,
} from "./workspace.ts";
export type Context = {
workspace: string;
baseUrl: string;
urlStore: string;
token: string;
};
async function tryResolveWorkspace(
opts: GlobalOptions,
): Promise<
{ isError: false; value: Workspace } | { isError: true; error: string }
> {
const cache = (opts as any).__secret_workspace;
if (cache) return cache;
if (opts.workspace) {
const e = await getWorkspaceByName(opts.workspace);
if (!e) {
return {
isError: true,
error: colors.red.underline("Given workspace does not exist."),
};
}
(opts as any).__secret_workspace = e;
return { isError: false, value: e };
}
const defaultWorkspace = await getActiveWorkspace(opts);
if (!defaultWorkspace) {
return {
isError: true,
error: colors.red.underline("No workspace given and no default set."),
};
}
return { isError: false, value: defaultWorkspace };
}
export async function resolveWorkspace(
opts: GlobalOptions,
): Promise<Workspace> {
const res = await tryResolveWorkspace(opts);
if (res.isError) {
console.log(res.error);
return Deno.exit(-1);
} else {
return res.value;
}
}
export async function requireLogin(opts: GlobalOptions) {
const workspace = await resolveWorkspace(opts);
let token = await tryGetLoginInfo(opts);
if (!token) {
token = workspace.token;
}
setClient(token, workspace.remote.substring(0, workspace.remote.length - 1));
try {
await UserService.globalWhoami();
} catch {
console.log(
"! Could not reach API given existing credentials. Attempting to reauth...",
);
const newToken = await loginInteractive(workspace.remote);
if (!newToken) {
throw new Error("Could not reauth");
}
removeWorkspace(workspace.name);
workspace.token = newToken;
addWorkspace(workspace);
setClient(
token,
workspace.remote.substring(0, workspace.remote.length - 1),
);
await UserService.globalWhoami();
}
}
export async function tryResolveVersion(
opts: GlobalOptions,
): Promise<number | undefined> {
if ((opts as any).__cache_version) {
return (opts as any).__cache_version;
}
const workspaceRes = await tryResolveWorkspace(opts);
if (workspaceRes.isError) return undefined;
const response = await fetch(
new URL(new URL(workspaceRes.value.remote).origin + "/api/version"),
);
const version = await response.text();
try {
return Number.parseInt(
version.split("-", 1)[0].replaceAll(".", "").replace("v", ""),
);
} catch {
return undefined;
}
}
export async function validatePath(
opts: GlobalOptions,
path: string,
): Promise<boolean> {
const backendVersion = await tryResolveVersion(opts);
if (path.startsWith("f")) {
if (!backendVersion || backendVersion >= 1550) {
return true;
}
console.log(
`Attempting to use folders, but the current remote does not have support. Remote version is ${backendVersion} but folders are supported from 1560.`,
);
return false;
}
if (
!(path.startsWith("g") ||
path.startsWith("u"))
) {
console.log(
colors.red(
"Given remote path looks invalid. Remote paths are typically of the form <u|g|f>/<username|group|folder>/...",
),
);
return false;
}
return true;
}