Files
windmill/typescript-client/client.js
Ruben Fiszel 7c44f1296d add tsdocs
2024-06-21 15:59:06 +02:00

693 lines
27 KiB
JavaScript

"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.usernameToEmail = exports.uint8ArrayToBase64 = exports.base64ToUint8Array = exports.getIdToken = exports.getResumeEndpoints = exports.getResumeUrls = exports.writeS3File = exports.loadS3FileStream = exports.loadS3File = exports.denoS3LightClientSettings = exports.databaseUrlFromResource = exports.setVariable = exports.getVariable = exports.getState = exports.getInternalState = exports.getFlowUserState = exports.setFlowUserState = exports.setState = exports.setInternalState = exports.setResource = exports.getStatePath = exports.resolveDefaultResource = exports.runScriptAsync = exports.task = exports.getResultMaybe = exports.getResult = exports.waitJob = exports.runScript = exports.getRootJobId = exports.getResource = exports.getWorkspace = exports.setClient = exports.SHARED_FOLDER = exports.WorkspaceService = exports.UserService = exports.SettingsService = exports.ScheduleService = exports.ScriptService = exports.VariableService = exports.ResourceService = exports.JobService = exports.GroupService = exports.GranularAclService = exports.FlowService = exports.AuditService = exports.AdminService = void 0;
const index_1 = require("./index");
const index_2 = require("./index");
var index_3 = require("./index");
Object.defineProperty(exports, "AdminService", { enumerable: true, get: function () { return index_3.AdminService; } });
Object.defineProperty(exports, "AuditService", { enumerable: true, get: function () { return index_3.AuditService; } });
Object.defineProperty(exports, "FlowService", { enumerable: true, get: function () { return index_3.FlowService; } });
Object.defineProperty(exports, "GranularAclService", { enumerable: true, get: function () { return index_3.GranularAclService; } });
Object.defineProperty(exports, "GroupService", { enumerable: true, get: function () { return index_3.GroupService; } });
Object.defineProperty(exports, "JobService", { enumerable: true, get: function () { return index_3.JobService; } });
Object.defineProperty(exports, "ResourceService", { enumerable: true, get: function () { return index_3.ResourceService; } });
Object.defineProperty(exports, "VariableService", { enumerable: true, get: function () { return index_3.VariableService; } });
Object.defineProperty(exports, "ScriptService", { enumerable: true, get: function () { return index_3.ScriptService; } });
Object.defineProperty(exports, "ScheduleService", { enumerable: true, get: function () { return index_3.ScheduleService; } });
Object.defineProperty(exports, "SettingsService", { enumerable: true, get: function () { return index_3.SettingsService; } });
Object.defineProperty(exports, "UserService", { enumerable: true, get: function () { return index_3.UserService; } });
Object.defineProperty(exports, "WorkspaceService", { enumerable: true, get: function () { return index_3.WorkspaceService; } });
exports.SHARED_FOLDER = "/shared";
function setClient(token, baseUrl) {
var _a, _b, _c;
if (baseUrl === undefined) {
baseUrl =
(_b = (_a = getEnv("BASE_INTERNAL_URL")) !== null && _a !== void 0 ? _a : getEnv("BASE_URL")) !== null && _b !== void 0 ? _b : "http://localhost:8000";
}
if (token === undefined) {
token = (_c = getEnv("WM_TOKEN")) !== null && _c !== void 0 ? _c : "no_token";
}
index_2.OpenAPI.WITH_CREDENTIALS = true;
index_2.OpenAPI.TOKEN = token;
index_2.OpenAPI.BASE = baseUrl + "/api";
}
exports.setClient = setClient;
const getEnv = (key) => {
var _a, _b, _c;
if (typeof window === "undefined") {
// node
return (_a = process === null || process === void 0 ? void 0 : process.env) === null || _a === void 0 ? void 0 : _a[key];
}
// browser
return (_c = (_b = window === null || window === void 0 ? void 0 : window.process) === null || _b === void 0 ? void 0 : _b.env) === null || _c === void 0 ? void 0 : _c[key];
};
/**
* Create a client configuration from env variables
* @returns client configuration
*/
function getWorkspace() {
var _a;
return (_a = getEnv("WM_WORKSPACE")) !== null && _a !== void 0 ? _a : "no_workspace";
}
exports.getWorkspace = getWorkspace;
/**
* Get a resource value by path
* @param path path of the resource, default to internal state path
* @param undefinedIfEmpty if the resource does not exist, return undefined instead of throwing an error
* @returns resource value
*/
function getResource(path, undefinedIfEmpty) {
return __awaiter(this, void 0, void 0, function* () {
const workspace = getWorkspace();
path = path !== null && path !== void 0 ? path : getStatePath();
try {
return yield index_1.ResourceService.getResourceValueInterpolated({
workspace,
path,
});
}
catch (e) {
if (undefinedIfEmpty && e.status === 404) {
return undefined;
}
else {
throw Error(`Resource not found at ${path} or not visible to you: ${e.body}`);
}
}
});
}
exports.getResource = getResource;
/**
* Get a resource value by path
* @param jobId job id to get the root job id from (default to current job)
* @returns root job id
*/
function getRootJobId(jobId) {
return __awaiter(this, void 0, void 0, function* () {
const workspace = getWorkspace();
jobId = jobId !== null && jobId !== void 0 ? jobId : getEnv("WM_JOB_ID");
if (jobId === undefined) {
throw Error("Job ID not set");
}
return yield index_1.JobService.getRootJobId({ workspace, id: jobId });
});
}
exports.getRootJobId = getRootJobId;
function runScript() {
return __awaiter(this, arguments, void 0, function* (path = null, hash_ = null, args = null, verbose = false) {
args = args || {};
if (verbose) {
console.info(`running \`${path}\` synchronously with args:`, args);
}
const jobId = yield runScriptAsync(path, hash_, args);
return yield waitJob(jobId, verbose);
});
}
exports.runScript = runScript;
function waitJob(jobId_1) {
return __awaiter(this, arguments, void 0, function* (jobId, verbose = false) {
while (true) {
// Implement your HTTP request logic here to get job result
const resultRes = yield getResultMaybe(jobId);
const started = resultRes.started;
const completed = resultRes.completed;
const success = resultRes.success;
if (!started && verbose) {
console.info(`job ${jobId} has not started yet`);
}
if (completed) {
const result = resultRes.result;
if (success) {
return result;
}
else {
const error = result.error;
throw new Error(`Job ${jobId} was not successful: ${JSON.stringify(error)}`);
}
}
if (verbose) {
console.info(`sleeping 0.5 seconds for jobId: ${jobId}`);
}
yield new Promise((resolve) => setTimeout(resolve, 500));
}
});
}
exports.waitJob = waitJob;
function getResult(jobId) {
return __awaiter(this, void 0, void 0, function* () {
const workspace = getWorkspace();
return yield index_1.JobService.getCompletedJobResult({ workspace, id: jobId });
});
}
exports.getResult = getResult;
function getResultMaybe(jobId) {
return __awaiter(this, void 0, void 0, function* () {
const workspace = getWorkspace();
return yield index_1.JobService.getCompletedJobResultMaybe({ workspace, id: jobId });
});
}
exports.getResultMaybe = getResultMaybe;
const STRIP_COMMENTS = /(\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s*=[^,\)]*(('(?:\\'|[^'\r\n])*')|("(?:\\"|[^"\r\n])*"))|(\s*=[^,\)]*))/gm;
const ARGUMENT_NAMES = /([^\s,]+)/g;
function getParamNames(func) {
const fnStr = func.toString().replace(STRIP_COMMENTS, "");
let result = fnStr
.slice(fnStr.indexOf("(") + 1, fnStr.indexOf(")"))
.match(ARGUMENT_NAMES);
if (result === null)
result = [];
return result;
}
function task(f) {
return (...y) => __awaiter(this, void 0, void 0, function* () {
const args = {};
const paramNames = getParamNames(f);
y.forEach((x, i) => (args[paramNames[i]] = x));
let req = yield fetch(`${index_2.OpenAPI.BASE}/w/${getWorkspace()}/jobs/run/workflow_as_code/${getEnv("WM_JOB_ID")}/${f.name}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${getEnv("WM_TOKEN")}`,
},
body: JSON.stringify({ args }),
});
let jobId = yield req.text();
console.log(`Started task ${f.name} as job ${jobId}`);
let r = yield waitJob(jobId);
console.log(`Task ${f.name} (${jobId}) completed`);
return r;
});
}
exports.task = task;
function runScriptAsync(path_1, hash_1, args_1) {
return __awaiter(this, arguments, void 0, function* (path, hash_, args, scheduledInSeconds = null) {
// Create a script job and return its job id.
if (path && hash_) {
throw new Error("path and hash_ are mutually exclusive");
}
args = args || {};
const params = {};
if (scheduledInSeconds) {
params["scheduled_in_secs"] = scheduledInSeconds;
}
let parentJobId = getEnv("WM_JOB_ID");
if (parentJobId !== undefined) {
params["parent_job"] = parentJobId;
}
let rootJobId = getEnv("WM_ROOT_FLOW_JOB_ID");
if (rootJobId != undefined && rootJobId != "") {
params["root_job"] = rootJobId;
}
let endpoint;
if (path) {
endpoint = `/w/${getWorkspace()}/jobs/run/p/${path}`;
}
else if (hash_) {
endpoint = `/w/${getWorkspace()}/jobs/run/h/${hash_}`;
}
else {
throw new Error("path or hash_ must be provided");
}
let url = new URL(index_2.OpenAPI.BASE + endpoint);
url.search = new URLSearchParams(params).toString();
return fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${index_2.OpenAPI.TOKEN}`,
},
body: JSON.stringify(args),
}).then((res) => res.text());
});
}
exports.runScriptAsync = runScriptAsync;
/**
* Resolve a resource value in case the default value was picked because the input payload was undefined
* @param obj resource value or path of the resource under the format `$res:path`
* @returns resource value
*/
function resolveDefaultResource(obj) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof obj === "string" && obj.startsWith("$res:")) {
return yield getResource(obj.substring(5), true);
}
else {
return obj;
}
});
}
exports.resolveDefaultResource = resolveDefaultResource;
function getStatePath() {
var _a;
const state_path = (_a = getEnv("WM_STATE_PATH_NEW")) !== null && _a !== void 0 ? _a : getEnv("WM_STATE_PATH");
if (state_path === undefined) {
throw Error("State path not set");
}
return state_path;
}
exports.getStatePath = getStatePath;
/**
* Set a resource value by path
* @param path path of the resource to set, default to state path
* @param value new value of the resource to set
* @param initializeToTypeIfNotExist if the resource does not exist, initialize it with this type
*/
function setResource(value, path, initializeToTypeIfNotExist) {
return __awaiter(this, void 0, void 0, function* () {
path = path !== null && path !== void 0 ? path : getStatePath();
const workspace = getWorkspace();
if (yield index_1.ResourceService.existsResource({ workspace, path })) {
yield index_1.ResourceService.updateResourceValue({
workspace,
path,
requestBody: { value },
});
}
else if (initializeToTypeIfNotExist) {
yield index_1.ResourceService.createResource({
workspace,
requestBody: { path, value, resource_type: initializeToTypeIfNotExist },
});
}
else {
throw Error(`Resource at path ${path} does not exist and no type was provided to initialize it`);
}
});
}
exports.setResource = setResource;
/**
* Set the state
* @param state state to set
* @deprecated use setState instead
*/
function setInternalState(state) {
return __awaiter(this, void 0, void 0, function* () {
yield setResource(state, undefined, "state");
});
}
exports.setInternalState = setInternalState;
/**
* Set the state
* @param state state to set
*/
function setState(state) {
return __awaiter(this, void 0, void 0, function* () {
yield setResource(state, undefined, "state");
});
}
exports.setState = setState;
/**
* Set a flow user state
* @param key key of the state
* @param value value of the state
*/
function setFlowUserState(key, value, errorIfNotPossible) {
return __awaiter(this, void 0, void 0, function* () {
if (value === undefined) {
value = null;
}
const workspace = getWorkspace();
try {
yield index_1.JobService.setFlowUserState({
workspace,
id: yield getRootJobId(),
key,
requestBody: value,
});
}
catch (e) {
if (errorIfNotPossible) {
throw Error(`Error setting flow user state at ${key}: ${e.body}`);
}
else {
console.error(`Error setting flow user state at ${key}: ${e.body}`);
}
}
});
}
exports.setFlowUserState = setFlowUserState;
/**
* Get a flow user state
* @param path path of the variable
*/
function getFlowUserState(key, errorIfNotPossible) {
return __awaiter(this, void 0, void 0, function* () {
const workspace = getWorkspace();
try {
return yield index_1.JobService.getFlowUserState({
workspace,
id: yield getRootJobId(),
key,
});
}
catch (e) {
if (errorIfNotPossible) {
throw Error(`Error setting flow user state at ${key}: ${e.body}`);
}
else {
console.error(`Error setting flow user state at ${key}: ${e.body}`);
}
}
});
}
exports.getFlowUserState = getFlowUserState;
// /**
// * Set the shared state
// * @param state state to set
// */
// export async function setSharedState(
// state: any,
// path = "state.json"
// ): Promise<void> {
// await Deno.writeTextFile(SHARED_FOLDER + "/" + path, JSON.stringify(state));
// }
// /**
// * Get the shared state
// * @param state state to set
// */
// export async function getSharedState(path = "state.json"): Promise<any> {
// return JSON.parse(await Deno.readTextFile(SHARED_FOLDER + "/" + path));
// }
/**
* Get the internal state
* @deprecated use getState instead
*/
function getInternalState() {
return __awaiter(this, void 0, void 0, function* () {
return yield getResource(getStatePath(), true);
});
}
exports.getInternalState = getInternalState;
/**
* Get the state shared across executions
*/
function getState() {
return __awaiter(this, void 0, void 0, function* () {
return yield getResource(getStatePath(), true);
});
}
exports.getState = getState;
/**
* Get a variable by path
* @param path path of the variable
* @returns variable value
*/
function getVariable(path) {
return __awaiter(this, void 0, void 0, function* () {
const workspace = getWorkspace();
try {
return yield index_1.VariableService.getVariableValue({ workspace, path });
}
catch (e) {
throw Error(`Variable not found at ${path} or not visible to you: ${e.body}`);
}
});
}
exports.getVariable = getVariable;
/**
* Set a variable by path, create if not exist
* @param path path of the variable
* @param value value of the variable
* @param isSecretIfNotExist if the variable does not exist, create it as secret or not (default: false)
* @param descriptionIfNotExist if the variable does not exist, create it with this description (default: "")
*/
function setVariable(path, value, isSecretIfNotExist, descriptionIfNotExist) {
return __awaiter(this, void 0, void 0, function* () {
const workspace = getWorkspace();
if (yield index_1.VariableService.existsVariable({ workspace, path })) {
yield index_1.VariableService.updateVariable({
workspace,
path,
requestBody: { value },
});
}
else {
yield index_1.VariableService.createVariable({
workspace,
requestBody: {
path,
value,
is_secret: isSecretIfNotExist !== null && isSecretIfNotExist !== void 0 ? isSecretIfNotExist : false,
description: descriptionIfNotExist !== null && descriptionIfNotExist !== void 0 ? descriptionIfNotExist : "",
},
});
}
});
}
exports.setVariable = setVariable;
function databaseUrlFromResource(path) {
return __awaiter(this, void 0, void 0, function* () {
const resource = yield getResource(path);
return `postgresql://${resource.user}:${resource.password}@${resource.host}:${resource.port}/${resource.dbname}?sslmode=${resource.sslmode}`;
});
}
exports.databaseUrlFromResource = databaseUrlFromResource;
// TODO(gb): need to investigate more how Polars and DuckDB work in TS
// export async function polarsConnectionSettings(s3_resource_path: string | undefined): Promise<any> {
// const workspace = getWorkspace();
// return await HelpersService.polarsConnectionSettingsV2({
// workspace: workspace,
// requestBody: {
// s3_resource_path: s3_resource_path
// }
// });
// }
// export async function duckdbConnectionSettings(s3_resource_path: string | undefined): Promise<any> {
// const workspace = getWorkspace();
// return await HelpersService.duckdbConnectionSettingsV2({
// workspace: workspace,
// requestBody: {
// s3_resource_path: s3_resource_path
// }
// });
// }
function denoS3LightClientSettings(s3_resource_path) {
return __awaiter(this, void 0, void 0, function* () {
const workspace = getWorkspace();
const s3Resource = yield index_1.HelpersService.s3ResourceInfo({
workspace: workspace,
requestBody: {
s3_resource_path: s3_resource_path,
},
});
let settings = Object.assign({}, s3Resource);
return settings;
});
}
exports.denoS3LightClientSettings = denoS3LightClientSettings;
/**
* Load the content of a file stored in S3. If the s3ResourcePath is undefined, it will default to the workspace S3 resource.
*
* ```typescript
* let fileContent = await wmill.loadS3FileContent(inputFile)
* // if the file is a raw text file, it can be decoded and printed directly:
* const text = new TextDecoder().decode(fileContentStream)
* console.log(text);
* ```
*/
function loadS3File(s3object_1) {
return __awaiter(this, arguments, void 0, function* (s3object, s3ResourcePath = undefined) {
const fileContentBlob = yield loadS3FileStream(s3object, s3ResourcePath);
if (fileContentBlob === undefined) {
return undefined;
}
// we read the stream until completion and put the content in an Uint8Array
const reader = fileContentBlob.stream().getReader();
const chunks = [];
while (true) {
const { value: chunk, done } = yield reader.read();
if (done) {
break;
}
chunks.push(chunk);
}
let fileContentLength = 0;
chunks.forEach((item) => {
fileContentLength += item.length;
});
let fileContent = new Uint8Array(fileContentLength);
let offset = 0;
chunks.forEach((chunk) => {
fileContent.set(chunk, offset);
offset += chunk.length;
});
return fileContent;
});
}
exports.loadS3File = loadS3File;
/**
* Load the content of a file stored in S3 as a stream. If the s3ResourcePath is undefined, it will default to the workspace S3 resource.
*
* ```typescript
* let fileContentBlob = await wmill.loadS3FileStream(inputFile)
* // if the content is plain text, the blob can be read directly:
* console.log(await fileContentBlob.text());
* ```
*/
function loadS3FileStream(s3object_1) {
return __awaiter(this, arguments, void 0, function* (s3object, s3ResourcePath = undefined) {
let params = {};
params["file_key"] = s3object.s3;
if (s3ResourcePath !== undefined) {
params["s3_resource_path"] = s3ResourcePath;
}
if (s3object.storage !== undefined) {
params["storage"] = s3object.storage;
}
const queryParams = new URLSearchParams(params);
// We use raw fetch here b/c OpenAPI generated client doesn't handle Blobs nicely
const fileContentBlob = yield fetch(`${index_2.OpenAPI.BASE}/w/${getWorkspace()}/job_helpers/download_s3_file?${queryParams}`, {
method: "GET",
headers: {
Authorization: `Bearer ${index_2.OpenAPI.TOKEN}`,
},
});
return fileContentBlob.blob();
});
}
exports.loadS3FileStream = loadS3FileStream;
/**
* Persist a file to the S3 bucket. If the s3ResourcePath is undefined, it will default to the workspace S3 resource.
*
* ```typescript
* const s3object = await writeS3File(s3Object, "Hello Windmill!")
* const fileContentAsUtf8Str = (await s3object.toArray()).toString('utf-8')
* console.log(fileContentAsUtf8Str)
* ```
*/
function writeS3File(s3object_1, fileContent_1) {
return __awaiter(this, arguments, void 0, function* (s3object, fileContent, s3ResourcePath = undefined) {
let fileContentBlob;
if (typeof fileContent === "string") {
fileContentBlob = new Blob([fileContent], {
type: "text/plain",
});
}
else {
fileContentBlob = fileContent;
}
const response = yield index_1.HelpersService.fileUpload({
workspace: getWorkspace(),
fileKey: s3object === null || s3object === void 0 ? void 0 : s3object.s3,
fileExtension: undefined,
s3ResourcePath: s3ResourcePath,
requestBody: fileContentBlob,
storage: s3object === null || s3object === void 0 ? void 0 : s3object.storage,
});
return {
s3: response.file_key,
};
});
}
exports.writeS3File = writeS3File;
/**
* Get URLs needed for resuming a flow after this step
* @param approver approver name
* @returns approval page UI URL, resume and cancel API URLs for resuming the flow
*/
function getResumeUrls(approver) {
return __awaiter(this, void 0, void 0, function* () {
var _a;
const nonce = Math.floor(Math.random() * 4294967295);
const workspace = getWorkspace();
return yield index_1.JobService.getResumeUrls({
workspace,
resumeId: nonce,
approver,
id: (_a = getEnv("WM_JOB_ID")) !== null && _a !== void 0 ? _a : "NO_JOB_ID",
});
});
}
exports.getResumeUrls = getResumeUrls;
/**
* @deprecated use getResumeUrls instead
*/
function getResumeEndpoints(approver) {
return getResumeUrls(approver);
}
exports.getResumeEndpoints = getResumeEndpoints;
/**
* Get an OIDC jwt token for auth to external services (e.g: Vault, AWS) (ee only)
* @param audience audience of the token
* @returns jwt token
*/
function getIdToken(audience) {
return __awaiter(this, void 0, void 0, function* () {
const workspace = getWorkspace();
return yield index_1.OidcService.getOidcToken({
workspace,
audience,
});
});
}
exports.getIdToken = getIdToken;
function base64ToUint8Array(data) {
return Uint8Array.from(atob(data), (c) => c.charCodeAt(0));
}
exports.base64ToUint8Array = base64ToUint8Array;
function uint8ArrayToBase64(arrayBuffer) {
let base64 = "";
const encodings = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const bytes = new Uint8Array(arrayBuffer);
const byteLength = bytes.byteLength;
const byteRemainder = byteLength % 3;
const mainLength = byteLength - byteRemainder;
let a, b, c, d;
let chunk;
// Main loop deals with bytes in chunks of 3
for (let i = 0; i < mainLength; i = i + 3) {
// Combine the three bytes into a single integer
chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
// Use bitmasks to extract 6-bit segments from the triplet
a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18
b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12
c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6
d = chunk & 63; // 63 = 2^6 - 1
// Convert the raw binary segments to the appropriate ASCII encoding
base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
}
// Deal with the remaining bytes and padding
if (byteRemainder == 1) {
chunk = bytes[mainLength];
a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2
// Set the 4 least significant bits to zero
b = (chunk & 3) << 4; // 3 = 2^2 - 1
base64 += encodings[a] + encodings[b] + "==";
}
else if (byteRemainder == 2) {
chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1];
a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10
b = (chunk & 1008) >> 4; // 1008 = (2^6 - 1) << 4
// Set the 2 least significant bits to zero
c = (chunk & 15) << 2; // 15 = 2^4 - 1
base64 += encodings[a] + encodings[b] + encodings[c] + "=";
}
return base64;
}
exports.uint8ArrayToBase64 = uint8ArrayToBase64;
/**
* Get email from workspace username
* This method is particularly useful for apps that require the email address of the viewer.
* Indeed, in the viewer context, WM_USERNAME is set to the username of the viewer but WM_EMAIL is set to the email of the creator of the app.
* @param username
* @returns email address
*/
function usernameToEmail(username) {
return __awaiter(this, void 0, void 0, function* () {
const workspace = getWorkspace();
return yield index_1.UserService.usernameToEmail({ username, workspace });
});
}
exports.usernameToEmail = usernameToEmail;