Compare commits

..

1 commit

Author SHA1 Message Date
alexweininger 36a976765c Fix error when deleting user 2021-05-31 01:06:20 -05:00
44 changed files with 184 additions and 782 deletions

View file

@ -1,48 +0,0 @@
name: Bug Report
description: File a bug report
title: "[Bug] "
labels: [bug]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: textarea
id: repro
attributes:
label: Reproduction steps
description: "How do you trigger this bug? Please walk us through it step by step."
value: |
1.
2.
3.
...
render: bash
validations:
required: true
- type: dropdown
id: version
attributes:
label: Version
description: What version of VS Code are you using?
options:
- Stable (Default)
- Insiders
validations:
required: true
- type: dropdown
id: os
attributes:
label: What operating system are you seeing the problem on?
multiple: true
options:
- All
- Windows
- macOS
- Linux
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell

View file

@ -26,6 +26,7 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run package
- run: npx vsce package
- uses: actions/upload-artifact@v2

View file

@ -6,21 +6,6 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
## [Unreleased]
## [0.1.3] - 2021-6-17
## Added
- New feature! JSON strings inside documents will now be automatically formatted as JSON when viewing documents. You can turn this feature off via the `appwrite.formatJsonStrings` setting.
## [0.1.2] - 2021-6-03
## Added
- Ability to set the `list`, `default` and `array` properties when creating a new collection. | [Issue #20](https://github.com/streamlux/vscode-appwrite/issues/20) | [PR #21](https://github.com/streamlux/vscode-appwrite/pull/21) | Thanks [@Maatteogekko](https://github.com/Maatteogekko)!
## [0.1.1] - 2021-5-31
## Added
- You can now easily create function tags from multiple places in the extension. [PR #19](https://github.com/streamlux/vscode-appwrite/pull/19)
## Fixed
- Fixed an error when deleting a user. [Issue #17](https://github.com/streamlux/vscode-appwrite/issues/17) [PR #18](https://github.com/streamlux/vscode-appwrite/pull/18) Thanks [@aadarshadhakalg](https://github.com/aadarshadhakalg)!
## [0.1.0] - 2021-5-29
## Functions!

View file

@ -18,15 +18,7 @@ From [appwrite.io](https://appwrite.io)
### Connect to multiple Appwrite projects
<img src="media/features/projects/projectsView1.gif" height="600">
### Creating function tags with ease!
![Functions feature](media/features/functions/CreateTag.gif)
### Create and manage Appwrite cloud functions, upload tags, and view function output
<img src="media/features/functions/functionsOverview.png" height="500">
![Mutliple projects](media/features/projects/projectsView1.gif)
### View database documents right inside VS Code.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 470 KiB

2
package-lock.json generated
View file

@ -1,6 +1,6 @@
{
"name": "vscode-appwrite",
"version": "0.0.9",
"version": "0.1.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View file

@ -2,7 +2,7 @@
"name": "vscode-appwrite",
"displayName": "Appwrite",
"description": "Manage your Appwrite resources right from VS Code!",
"version": "0.1.3",
"version": "0.1.0",
"engines": {
"vscode": "^1.55.0"
},
@ -40,187 +40,151 @@
{
"command": "vscode-appwrite.Connect",
"title": "Connect to Appwrite",
"category": "Appwrite"
"category": ""
},
{
"command": "vscode-appwrite.CreateUser",
"title": "Create user",
"icon": "$(add)",
"category": "Appwrite"
"icon": "$(add)"
},
{
"command": "vscode-appwrite.DeleteUser",
"title": "Delete user",
"icon": "$(trash)",
"category": "Appwrite"
"icon": "$(trash)"
},
{
"command": "vscode-appwrite.GetUserLogs",
"title": "Get user logs",
"icon": "$(output)",
"category": "Appwrite"
"icon": "$(output)"
},
{
"command": "vscode-appwrite.openUserInConsole",
"title": "View user in Appwrite console",
"icon": "$(link-external)",
"category": "Appwrite"
"icon": "$(link-external)"
},
{
"command": "vscode-appwrite.viewUserPrefs",
"title": "View user preferences",
"icon": "$(json)",
"category": "Appwrite"
"icon": "$(json)"
},
{
"command": "vscode-appwrite.refreshEntry",
"title": "Refresh",
"icon": "$(refresh)",
"category": "Appwrite"
"icon": "$(refresh)"
},
{
"command": "vscode-appwrite.copyUserId",
"title": "Copy user ID",
"icon": "$(clippy)",
"category": "Appwrite"
"icon": "$(clippy)"
},
{
"command": "vscode-appwrite.copyUserEmail",
"title": "Copy user email",
"icon": "$(clippy)",
"category": "Appwrite"
"icon": "$(clippy)"
},
{
"command": "vscode-appwrite.refreshUsersList",
"title": "Refresh users list",
"icon": "$(refresh)",
"category": "Appwrite"
"icon": "$(refresh)"
},
{
"command": "vscode-appwrite.OpenUsersDocumentation",
"title": "Open documentation",
"icon": "$(book)",
"category": "Appwrite"
"icon": "$(book)"
},
{
"command": "vscode-appwrite.OpenDatabaseDocumentation",
"title": "Open documentation",
"icon": "$(book)",
"category": "Appwrite"
"icon": "$(book)"
},
{
"command": "vscode-appwrite.viewDocumentAsJson",
"title": "View as JSON",
"category": "Appwrite"
"title": "View as JSON"
},
{
"command": "vscode-appwrite.viewCollectionAsJson",
"title": "View collection as JSON",
"category": "Appwrite"
"title": "View collection as JSON"
},
{
"command": "vscode-appwrite.refreshCollection",
"title": "Refresh",
"icon": "$(refresh)",
"category": "Appwrite"
"icon": "$(refresh)"
},
{
"command": "vscode-appwrite.createRule",
"title": "Create collection rule",
"icon": "$(add)",
"category": "Appwrite"
"icon": "$(add)"
},
{
"command": "vscode-appwrite.removeRule",
"title": "Remove collection rule",
"category": "Appwrite"
"title": "Remove collection rule"
},
{
"command": "vscode-appwrite.deleteDocument",
"title": "Delete document",
"category": "Appwrite"
"title": "Delete document"
},
{
"command": "vscode-appwrite.deleteCollection",
"title": "Delete collection",
"category": "Appwrite"
"title": "Delete collection"
},
{
"command": "vscode-appwrite.refreshCollectionsList",
"title": "Refresh",
"icon": "$(refresh)",
"category": "Appwrite"
"icon": "$(refresh)"
},
{
"command": "vscode-appwrite.createCollection",
"title": "Create collection",
"icon": "$(add)",
"category": "Appwrite"
"icon": "$(add)"
},
{
"command": "vscode-appwrite.createPermission",
"title": "Create permission",
"icon": "$(add)",
"category": "Appwrite"
"icon": "$(add)"
},
{
"command": "vscode-appwrite.deletePermission",
"title": "Delete permission",
"icon": "$(trash)",
"category": "Appwrite"
"icon": "$(trash)"
},
{
"command": "vscode-appwrite.editPermission",
"title": "Edit permission",
"icon": "$(edit)",
"category": "Appwrite"
"icon": "$(edit)"
},
{
"command": "vscode-appwrite.refreshHealth",
"title": "Refresh health",
"icon": "$(refresh)",
"category": "Appwrite"
"icon": "$(refresh)"
},
{
"command": "vscode-appwrite.openHealthDocumentation",
"title": "Open health documentation",
"icon": "$(book)",
"category": "Appwrite"
"icon": "$(book)"
},
{
"command": "vscode-appwrite.refreshStorage",
"title": "Refresh storage",
"icon": "$(refresh)",
"category": "Appwrite"
"icon": "$(refresh)"
},
{
"command": "vscode-appwrite.openStorageDocumentation",
"title": "Open storage documentation",
"icon": "$(book)",
"category": "Appwrite"
"icon": "$(book)"
},
{
"command": "vscode-appwrite.addProject",
"title": "Add Appwrite project",
"icon": "$(plus)",
"category": "Appwrite"
"icon": "$(plus)"
},
{
"command": "vscode-appwrite.setActiveProject",
"title": "Set as active",
"category": "Appwrite"
"title": "Set as active"
},
{
"command": "vscode-appwrite.refreshProjects",
"title": "Refresh projects",
"icon": "$(refresh)",
"category": "Appwrite"
},
{
"command": "vscode-appwrite.refreshFunctions",
"title": "Refresh functions",
"icon": "$(refresh)",
"category": "Appwrite"
"icon": "$(refresh)"
},
{
"command": "vscode-appwrite.refreshFunctions",
@ -230,115 +194,91 @@
{
"command": "vscode-appwrite.removeProject",
"title": "Remove project",
"icon": "$(trash)",
"category": "Appwrite"
"icon": "$(trash)"
},
{
"command": "vscode-appwrite.CreateTag",
"title": "Create function tag",
"icon": "$(cloud-upload)",
"shortTitle": "Create function tag",
"category": "Appwrite"
"icon": "$(cloud-upload)"
},
{
"command": "vscode-appwrite.deleteTag",
"title": "Delete tag",
"icon": "$(trash)",
"category": "Appwrite"
"icon": "$(trash)"
},
{
"command": "vscode-appwrite.CreateExecution",
"title": "Execute",
"category": "Appwrite"
"title": "Execute"
},
{
"command": "vscode-appwrite.activateTag",
"title": "Activate",
"category": "Appwrite"
"title": "Activate"
},
{
"command": "vscode-appwrite.editValue",
"title": "Edit",
"icon": "$(edit)",
"category": "Appwrite"
"icon": "$(edit)"
},
{
"command": "vscode-appwrite.deleteFunction",
"title": "Delete",
"icon": "$(trash)",
"category": "Appwrite"
"icon": "$(trash)"
},
{
"command": "vscode-appwrite.openFunctionsDocumentation",
"title": "Open functions documentation",
"icon": "$(book)",
"category": "Appwrite"
"icon": "$(book)"
},
{
"command": "vscode-appwrite.createFunction",
"title": "Create function",
"icon": "$(add)",
"category": "Appwrite"
"icon": "$(add)"
},
{
"command": "vscode-appwrite.createFunctionVar",
"title": "Create variable",
"icon": "$(add)",
"category": "Appwrite"
"icon": "$(add)"
},
{
"command": "vscode-appwrite.deleteFunctionVar",
"title": "Delete variable",
"icon": "$(trash)",
"category": "Appwrite"
"icon": "$(trash)"
},
{
"command": "vscode-appwrite.viewExecutionOutput",
"title": "View execution stdout",
"enablement": "viewItem =~ /^((execution|execution_outputOnly))$/",
"category": "Appwrite"
"enablement": "viewItem =~ /^((execution|execution_outputOnly))$/"
},
{
"command": "vscode-appwrite.viewExecutionErrors",
"title": "View execution stderr",
"enablement": "viewItem =~ /^((execution|execution_errorOnly))$/",
"category": "Appwrite"
"enablement": "viewItem =~ /^((execution|execution_errorOnly))$/"
},
{
"command": "vscode-appwrite.copyExecutionOutput",
"title": "Copy execution stdout",
"enablement": "viewItem =~ /^((execution|execution_outputOnly))$/",
"category": "Appwrite"
"enablement": "viewItem =~ /^((execution|execution_outputOnly))$/"
},
{
"command": "vscode-appwrite.copyExecutionErrors",
"title": "Copy execution stderr",
"enablement": "viewItem =~ /^((execution|execution_errorOnly))$/",
"category": "Appwrite"
"enablement": "viewItem =~ /^((execution|execution_errorOnly))$/"
},
{
"command": "vscode-appwrite.openExecutionsInBrowser",
"title": "View executions in browser",
"enablement": "viewItem =~ /^(executions)$/",
"icon": "$(link-external)",
"category": "Appwrite"
"icon": "$(link-external)"
},
{
"command": "vscode-appwrite.openFunctionTagsInBrowser",
"title": "Open function tags in browser",
"icon": "$(link-external)",
"category": "Appwrite"
"icon": "$(link-external)"
},
{
"command": "vscode-appwrite.openFunctionSettingsInBrowser",
"title": "Open function settings in browser",
"icon": "$(link-external)",
"category": "Appwrite"
},
{
"command": "vscode-appwrite.viewMore",
"title": "View more",
"category": "Appwrite"
"icon": "$(link-external)"
}
],
"views": {
@ -630,9 +570,6 @@
}
],
"commandPalette": [
{
"command": "vscode-appwrite.CreateTag"
},
{
"command": "vscode-appwrite.Connect"
},
@ -726,11 +663,6 @@
"type": "string",
"default": "",
"markdownDescription": "Project id of the active project, see [docs](https://github.com/streamlux/vscode-appwrite/) for more information."
},
"appwrite.formatJsonStrings": {
"type": "boolean",
"default": true,
"markdownDescription": "Format JSON strings when viewing documents"
}
}
}

8
src/appwrite.d.ts vendored
View file

@ -276,7 +276,7 @@ export type CollectionsList = {
collections: Collection[];
};
export type CreatedRule = Omit<Rule, "$id" | "$collection">;
export type CreatedRule = Omit<Rule, "$id" | "$collection" | "default" | "list">;
export type Rule = {
$id: string;
@ -284,10 +284,10 @@ export type Rule = {
type: string;
key: string;
label: string;
default?: any;
required: boolean;
default: string;
array: boolean;
list?: string[];
required: boolean;
list: string[];
};
export type Permissions = {

View file

@ -1,10 +1,10 @@
import { Client, Execution, ExecutionList, FunctionsClient, FunctionsList, Tag, TagList, Vars } from "../appwrite";
import { Client, Execution, ExecutionList, FunctionsClient, TagList, Vars } from "../appwrite";
import { AppwriteSDK } from '../constants';
import AppwriteCall from '../utils/AppwriteCall';
import { ReadStream } from 'node:fs';
export class Functions {
public readonly functions: FunctionsClient;
private readonly functions: FunctionsClient;
constructor(client: Client) {
this.functions = new AppwriteSDK.Functions(client);
@ -13,7 +13,7 @@ export class Functions {
public async create(name: string, execute: string[], env: string, vars?: Vars, events?: string[], schedule?: string, timeout?: number): Promise<any> {
return await AppwriteCall(this.functions.create(name, execute, env, vars, events, schedule, timeout));
}
public async list(search?: string, offset?: number, limit?: number, orderType?: 'ASC' | 'DESC'): Promise<FunctionsList | undefined> {
public async list(search?: string, offset?: number, limit?: number, orderType?: 'ASC' | 'DESC'): Promise<any> {
return await AppwriteCall(this.functions.list(search, offset, limit, orderType));
}
public async get(functionId: string): Promise<any> {
@ -28,7 +28,7 @@ export class Functions {
public async delete(functionId: string): Promise<void> {
return await AppwriteCall(this.functions.delete(functionId));
}
public async createTag(functionId: string, command: string, code: ReadStream): Promise<Tag | undefined> {
public async createTag(functionId: string, command: string, code: ReadStream): Promise<any> {
return await AppwriteCall(this.functions.createTag(functionId, command, code));
}
public async listTags(id: string, search?: string, limit?: number, offset?: number, orderType?: 'ASC' | 'DESC'): Promise<TagList | undefined> {
@ -40,11 +40,11 @@ export class Functions {
public async deleteTag(functionId: string, tagId: string): Promise<void> {
return await AppwriteCall(this.functions.deleteTag(functionId, tagId));
}
public async createExecution(functionId: string, data?: string): Promise<Execution | undefined> {
public async createExecution(functionId: string, data?: string): Promise<any> {
return await AppwriteCall(this.functions.createExecution(functionId, data));
}
public async listExecutions(functionId: string, search?: string, limit?: number, offset?: number, orderType?: 'ASC' | 'DESC'): Promise<ExecutionList | undefined> {
return await AppwriteCall(this.functions.listExecutions(functionId, search, limit, offset, orderType));
return await AppwriteCall(this.functions.listExecutions(functionId, search, offset, limit, orderType));
}
public async getExecution(functionId: string, executionId: string): Promise<Execution | undefined> {
return await AppwriteCall(this.functions.getExecution(functionId, executionId));

View file

@ -1,4 +1,4 @@
import { EditableTreeItem } from '../../tree/common/editable/SimpleEditableTreeItem';
import { EditableTreeItem } from '../../tree/common/SimpleEditableTreeItem';
export async function editValue(treeItem: EditableTreeItem): Promise<void> {
if (treeItem === undefined) {

View file

@ -1,5 +0,0 @@
import { AppwriteTreeItemBase } from '../../ui/AppwriteTreeItemBase';
export async function viewMore(treeItem: AppwriteTreeItemBase<any>): Promise<void> {
await treeItem.viewMore();
}

View file

@ -10,13 +10,15 @@ export async function createRule(rulesTreeItem: RulesTreeItem): Promise<void> {
return;
}
const ruleContext = await createRuleWizard();
const collection = rulesTreeItem.parent.collection;
const ruleContext = await createRuleWizard(collection);
if (ruleContext) {
const newRule: CreatedRule = {
...ruleContext,
type: ruleContext.type,
required: true,
array: false,
};
databaseClient.createRule(collection, newRule);

View file

@ -1,30 +1,8 @@
import { workspace } from "vscode";
import { DocumentTreeItem } from "../../tree/database/DocumentTreeItem";
import { openReadOnlyJson } from "../../ui/openReadonlyContent";
function parseJSONString(str: string): { valid: boolean; value: any } {
try {
return { value: JSON.parse(str), valid: true };
} catch (e) {
return { value: str, valid: false };
}
}
export async function viewDocumentAsJson(documentTreeItem: DocumentTreeItem): Promise<void> {
const document = documentTreeItem.document;
const documentId = document["$id"];
const formatJsonStrings = workspace.getConfiguration("appwrite").get<Boolean>("formatJsonStrings");
if (formatJsonStrings) {
Object.entries(document).forEach(([key, value]) => {
if (typeof value === "string") {
const result = parseJSONString(value);
document[key] = result.value;
}
});
}
const documentId = documentTreeItem.document["$id"];
await openReadOnlyJson(
{
label: documentId,

View file

@ -1,8 +1,7 @@
import { Tag } from '../../appwrite';
import { functionsClient } from '../../client';
import { TagTreeItem } from '../../tree/functions/tags/TagTreeItem';
export async function activateTag(tagItem: TagTreeItem | Tag): Promise<void> {
const tag = tagItem instanceof TagTreeItem ? tagItem.tag : tagItem;
export async function activateTag(tagItem: TagTreeItem): Promise<void> {
const tag = tagItem.tag;
await functionsClient?.updateTag(tag.functionId, tag.$id);
}

View file

@ -1,57 +1,10 @@
import { window } from 'vscode';
import { Execution } from '../../appwrite';
import { functionsClient } from '../../client';
import { ext } from '../../extensionVariables';
import { FunctionTreeItem } from '../../tree/functions/FunctionTreeItem';
import { sleep } from '../../utils/sleep';
import { viewExecutionErrors } from './viewExecutionErrors';
import { viewExecutionOutput } from './viewExecutionOutput';
export async function createExecution(functionTreeItem: FunctionTreeItem): Promise<void> {
const func = functionTreeItem.func;
await executeFunction(func.$id);
}
export async function executeFunction(functionId: string): Promise<void> {
ext.outputChannel.appendLog(`Creating execution for function with ID: ${functionId}`);
let execution = await functionsClient?.createExecution(functionId);
ext.outputChannel.appendLog(JSON.stringify(execution, null, 2));
await ext.tree?.functions?.refresh();
if (execution === undefined) {
return;
}
execution = await waitForExecution(execution);
ext.tree?.functions?.refresh();
if (execution === undefined) {
return;
}
const failed = execution.status === "failed";
const item = !failed ? "View output" : "View errors";
const action = await window.showInformationMessage(`Execution ${failed ? "failed" : "completed"} in ${execution.time.toFixed(2)}s.`, item);
if (action === item) {
if (item === "View output") {
await viewExecutionOutput(execution);
return;
}
await viewExecutionErrors(execution);
return;
}
}
async function waitForExecution(execution: Execution | undefined): Promise<Execution | undefined> {
if (execution === undefined) {
return;
}
if (execution.status === "processing" || execution.status === "waiting") {
await sleep(5000);
ext.outputChannel.appendLog("Execution still ...");
return await waitForExecution(await functionsClient?.getExecution(execution.functionId, execution.$id));
}
return execution;
ext.outputChannel.appendLog(`Creating execution for function ${func.name}`);
await functionsClient?.createExecution(func.$id);
}

View file

@ -1,164 +1,41 @@
import { ProgressLocation, QuickPickItem, Uri, window, workspace } from "vscode";
import { functionsClient } from "../../client";
import { ProgressLocation, Uri, window } from "vscode";
import { functionsClient, storageClient } from "../../client";
import { getTarReadStream } from "../../utils/tar";
import { ext } from "../../extensionVariables";
import * as fs from "fs";
import { TagsTreeItem } from "../../tree/functions/tags/TagsTreeItem";
import { selectWorkspaceFolder } from "../../utils/workspace";
import { ProgressMessage } from "../../utils/types";
import { Tag } from "../../appwrite";
import { activateTag } from "./activateTag";
export async function createTag(item?: TagsTreeItem | Uri): Promise<void> {
export async function createTag(item: TagsTreeItem | Uri): Promise<void> {
if (item instanceof Uri) {
const functions = await functionsClient?.list();
if (functions === undefined) {
return;
}
const pick = await window.showQuickPick(
functions.functions.map<QuickPickItem>(
(func): QuickPickItem => ({ label: func.name, description: func.env, detail: func.$id })
),
{ placeHolder: "Select a function to create tag" }
);
if (pick === undefined || pick.detail === undefined) {
return;
}
const tags = await functionsClient?.listTags(pick.detail);
let value;
if (tags && tags.tags.length > 0) {
value = tags.tags[tags.tags.length - 1].command;
}
const command = await window.showInputBox({ value, prompt: "Command to run your code" });
if (command === undefined) {
return;
}
const tag = await window.withProgress(
{ location: ProgressLocation.Notification, title: "Creating tag..." },
async (progress, _token) => {
if (pick.detail === undefined) {
return;
}
return await createTagFromUri(pick.detail, command, item, progress);
}
);
if (tag) {
await tagNotification(tag);
}
window.withProgress({ location: ProgressLocation.Notification, title: "Creating tag..." }, async (_progress, _token) => {
await createTagFromUri(item);
});
return;
}
if (item instanceof TagsTreeItem) {
const func = item.parent.func;
const folder = await selectWorkspaceFolder("Select folder of your function code.");
if (folder === undefined || folder === "") {
return;
}
const tags = await functionsClient?.listTags(func.$id);
let value;
if (tags && tags.tags.length > 0) {
value = tags.tags[tags.tags.length - 1].command;
}
const command = await window.showInputBox({ value, prompt: "Command to run your code" });
if (command === undefined) {
return;
}
const tag = await window.withProgress(
{ location: ProgressLocation.Notification, title: "Creating tag..." },
async (progress, _token) => {
return await createTagFromUri(func.$id, command, Uri.parse(folder), progress);
}
);
if (tag) {
await tagNotification(tag);
return;
}
}
if (item === undefined) {
const functions = await functionsClient?.list();
if (functions === undefined) {
return;
}
const pick = await window.showQuickPick(
functions.functions.map<QuickPickItem>(
(func): QuickPickItem => ({ label: func.name, description: func.env, detail: func.$id })
),
{ placeHolder: "Select a function to create tag" }
);
if (pick === undefined || pick.detail === undefined) {
return;
}
const funcId = pick.detail;
const folder = await selectWorkspaceFolder("Select folder of your function code.");
const tags = await functionsClient?.listTags(funcId);
let value;
if (tags && tags.tags.length > 0) {
value = tags.tags[tags.tags.length - 1].command;
}
const command = await window.showInputBox({ value, prompt: "Command to run your code" });
if (command === undefined) {
return;
}
const tag = await window.withProgress(
{ location: ProgressLocation.Notification, title: "Creating tag..." },
async (progress, _token) => {
return await createTagFromUri(funcId, command, Uri.parse(folder), progress);
}
);
if (tag) {
await tagNotification(tag);
return;
}
console.log(folder);
window.withProgress({ location: ProgressLocation.Notification, title: "Creating tag..." }, async (_progress, _token) => {
await createTagFromUri(Uri.parse(folder));
});
}
}
async function createTagFromUri(functionId: string, command: string, uri: Uri, progress: ProgressMessage): Promise<Tag | undefined> {
progress.report({ message: "Creating tarball", increment: 10 });
async function createTagFromUri(uri: Uri): Promise<void> {
const tarFilePath = await getTarReadStream(uri);
if (functionsClient === undefined) {
return;
}
let tarFilePath;
try {
tarFilePath = await getTarReadStream(uri);
} catch (e) {
window.showErrorMessage("Error creating tar file.\n" + e);
return;
}
if (tarFilePath === undefined) {
window.showErrorMessage("Failed to create tar file.");
ext.outputChannel.appendLog("Failed to create tar file.");
ext.outputChannel.appendLog("Error creating tar file.");
return;
}
// somehow makes the upload work
await workspace.fs.readFile(Uri.file(tarFilePath));
progress.report({ message: "Uploading tag", increment: 60 });
try {
return await functionsClient.createTag(functionId, command, fs.createReadStream(tarFilePath));
await functionsClient.createTag("60b1836a8e5d9", "python ./hello.py", fs.createReadStream(tarFilePath));
await storageClient?.createFile(fs.createReadStream(tarFilePath));
} catch (e) {
ext.outputChannel.appendLog("Creating tag error: " + e);
}
}
async function tagNotification(tag: Tag): Promise<void> {
ext.tree?.functions?.refresh();
if (tag) {
const action = await window.showInformationMessage(
`Successfully created tag with size ${tag.size}B.`,
"Activate tag",
"View in console"
);
if (action === "Activate tag") {
await activateTag(tag);
}
if (action === "View in console") {
//
}
return;
}
}

View file

@ -1,16 +1,11 @@
import { Execution } from '../../appwrite';
import { ExecutionTreeItem } from "../../tree/functions/executions/ExecutionTreeItem";
import { openReadOnlyContent } from "../../ui/openReadonlyContent";
export async function viewExecutionErrors(executionItem: ExecutionTreeItem | Execution): Promise<void> {
export async function viewExecutionErrors(executionItem: ExecutionTreeItem): Promise<void> {
if (executionItem === undefined) {
return;
}
let execution = executionItem as Execution;
if (executionItem instanceof ExecutionTreeItem) {
execution = executionItem.execution;
}
await openReadOnlyContent({ label: `Execution stderr`, fullId: `${execution.$id}-errors.txt` }, execution.stderr, '.txt');
const execution = executionItem.execution;
await openReadOnlyContent({ label: `${executionItem.parent.parent.func.name} execution stderr`, fullId: `${execution.$id}-errors.txt` }, execution.stderr, '.txt');
}

View file

@ -1,19 +1,11 @@
import { Execution } from '../../appwrite';
import { ExecutionTreeItem } from "../../tree/functions/executions/ExecutionTreeItem";
import { openReadOnlyContent } from "../../ui/openReadonlyContent";
export async function viewExecutionOutput(executionItem: ExecutionTreeItem | Execution): Promise<void> {
export async function viewExecutionOutput(executionItem: ExecutionTreeItem): Promise<void> {
if (executionItem === undefined) {
return;
}
let execution = executionItem as Execution;
if (executionItem instanceof ExecutionTreeItem) {
execution = executionItem.execution;
}
console.log(execution.dateCreated);
await openReadOnlyContent({ label: `Execution stdout`, fullId: `${execution.$id}-output.txt` }, execution.stdout, '.txt');
const execution = executionItem.execution;
await openReadOnlyContent({ label: `${executionItem.parent.parent.func.name} execution stdout`, fullId: `${execution.$id}-output.txt` }, execution.stdout, '.txt');
}

View file

@ -42,8 +42,6 @@ import { openExecutionsInBrowser } from './functions/openExecutionsInBrowser';
import { openFunctionSettingsInBrowser } from './functions/openFunctionSettingsInBrowser';
import { openFunctionTagsInBrowser } from './functions/openFunctionTagsInBrowser';
import { viewMore } from './common/viewMore';
class CommandRegistrar {
constructor(private readonly context: ExtensionContext) {}
@ -76,7 +74,6 @@ export function registerCommands(context: ExtensionContext): void {
/** Common **/
registerCommand("editValue", editValue);
registerCommand("viewMore", viewMore);
/** General **/
registerCommand("Connect", connectAppwrite, "all");

View file

@ -17,7 +17,7 @@ export type AppwriteTree = {
};
export type Ext = {
context: ExtensionContext;
context?: ExtensionContext;
outputChannel: AppwriteOutputChannel;
tree?: AppwriteTree;
};

View file

@ -1,13 +0,0 @@
import { TreeItem } from "vscode";
export abstract class EditableTreeItemBase<T> extends TreeItem {
public abstract setValue(value: T): Promise<void>;
constructor(contextValuePrefix: string, public readonly value: T, description?: string) {
super(typeof value === "string" ? value : "No label");
this.contextValue = `editable_${contextValuePrefix}`;
this.description = description ?? contextValuePrefix;
}
public abstract prompt(): Promise<void>;
}

View file

@ -1,38 +0,0 @@
import { QuickPickItem, QuickPickOptions, window } from "vscode";
import { EditableTreeItemBase } from "./EditableTreeItemBase";
export abstract class EnumEditableTreeItemBase extends EditableTreeItemBase<string[]> {
public abstract options: string[] | QuickPickItem[];
public quickPickOptions: QuickPickOptions;
constructor(contextValuePrefix: string, public readonly value: string[], description?: string) {
super(contextValuePrefix, value, description);
this.quickPickOptions = {};
}
public async prompt(): Promise<void> {
const value = await window.showQuickPick(
this.options.map<QuickPickItem>((option: QuickPickItem | string): QuickPickItem => {
if (typeof option === "string") {
return { label: option, picked: this.value.includes(option) };
}
const picked = this.value.includes(option.label);
return { ...option, picked, alwaysShow: picked };
}).sort((a, b) => {
if (a.picked) {
return -1;
}
if (b.picked) {
return 1;
}
return 0;
}),
{ ...this.quickPickOptions, canPickMany: true }
);
if (value !== undefined) {
this.setValue(value.map((item) => item.label));
}
}
}

View file

@ -1,18 +0,0 @@
import { TreeItem, window } from "vscode";
export class EditableTreeItem extends TreeItem {
public readonly setValue: (value: string) => Promise<void>;
constructor(label: string, contextValuePrefix: string, public readonly value: string, setValue: (value: string) => Promise<void>) {
super(label);
this.setValue = setValue;
this.contextValue = `editable_${contextValuePrefix}`;
}
public async prompt(): Promise<void> {
const value = await window.showInputBox({ value: this.value });
if (value !== undefined) {
this.setValue(value);
}
}
}

View file

@ -1,22 +0,0 @@
import { InputBoxOptions, window } from "vscode";
import { EditableTreeItemBase } from "./EditableTreeItemBase";
export abstract class StringEditableTreeItemBase extends EditableTreeItemBase<string> {
public abstract setValue(value: string): Promise<void>;
public inputBoxOptions: InputBoxOptions;
constructor(contextValuePrefix: string, public readonly value: string, description?: string) {
super(contextValuePrefix, value, description);
this.inputBoxOptions = {
prompt: description,
};
}
public async prompt(): Promise<void> {
const value = await window.showInputBox({ value: this.value, ...this.inputBoxOptions });
if (value !== undefined) {
this.setValue(value);
}
}
}

View file

@ -4,8 +4,8 @@ import AppwriteCall from "../../utils/AppwriteCall";
import { Collection, CollectionsList } from "../../appwrite";
import { CollectionTreeItem } from "./CollectionTreeItem";
import { AppwriteSDK } from "../../constants";
import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase";
import { ext } from '../../extensionVariables';
import { AppwriteTreeItemBase } from '../../ui/AppwriteTreeItemBase';
export class DatabaseTreeItemProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
private _onDidChangeTreeData: vscode.EventEmitter<vscode.TreeItem | undefined | void> = new vscode.EventEmitter<
@ -34,7 +34,7 @@ export class DatabaseTreeItemProvider implements vscode.TreeDataProvider<vscode.
}
if (parent instanceof AppwriteTreeItemBase) {
return await parent.getChildren?.() ?? [];
return parent.getChildren?.() ?? [];
}
const databaseSdk = new AppwriteSDK.Database(client);

View file

@ -44,7 +44,7 @@ export class FunctionsTreeItemProvider implements vscode.TreeDataProvider<vscode
}
if (parent instanceof AppwriteTreeItemBase) {
return await parent.getChildren?.() ?? [];
return parent.getChildren?.() ?? [];
}
return [];

View file

@ -1,5 +1,7 @@
import { MarkdownString, ThemeColor, ThemeIcon, TreeItem } from "vscode";
import { Execution, ExecutionStatus } from "../../../appwrite";
import { functionsClient } from "../../../client";
import { ext } from "../../../extensionVariables";
import { msToDate } from "../../../utils/date";
import { ExecutionsTreeItem } from "./ExecutionsTreeItem";
@ -10,11 +12,17 @@ const executionStatusIcons: Record<ExecutionStatus, ThemeIcon> = {
failed: new ThemeIcon("circle-filled", new ThemeColor("testing.iconFailed")),
};
function sleep(ms: number) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
export class ExecutionTreeItem extends TreeItem {
public isAutoRefreshing: boolean = false;
private refreshCount: number = 0;
constructor(public readonly parent: ExecutionsTreeItem, public execution: Execution) {
constructor(public readonly parent: ExecutionsTreeItem, public readonly execution: Execution) {
super(execution.$id);
this.label = this.getLabel(execution);
this.iconPath = executionStatusIcons[execution.status];
@ -23,45 +31,40 @@ export class ExecutionTreeItem extends TreeItem {
this.description = execution.trigger;
this.contextValue = this.getContextValue(execution);
this.isAutoRefreshing = execution.status === "processing" || execution.status === "waiting";
// if (this.isAutoRefreshing) {
// this.autoRefresh();
// }
this.autoRefresh();
}
// async autoRefresh(): Promise<void> {
// if (!this.isAutoRefreshing && this.refreshCount < 5) {
// return;
// }
// this.refreshCount++;
// ext.outputChannel.appendLog("Refreshing execution.");
// const execution = await functionsClient?.getExecution(this.parent.parent.func.$id, this.execution.$id);
async autoRefresh(): Promise<void> {
if (!this.isAutoRefreshing) {
return;
}
this.refreshCount++;
ext.outputChannel.appendLog("Refreshing execution.");
const execution = await functionsClient?.getExecution(this.parent.parent.func.$id, this.execution.$id);
// if (!execution) {
// ext.outputChannel.appendLog("Execution is undefined");
// this.isAutoRefreshing = false;
// return;
// }
// this.execution = execution;
// this.contextValue = this.getContextValue(execution);
// this.iconPath = executionStatusIcons[execution.status];
// this.label = this.getLabel(execution);
// this.isAutoRefreshing = execution.status === "processing" || execution.status === "waiting";
// ext.tree?.functions?.refreshChild(this);
// await sleep(1000);
// this.autoRefresh();
// }
if (!execution) {
ext.outputChannel.appendLog("Execution is undefined");
this.isAutoRefreshing = false;
return;
}
this.contextValue = this.getContextValue(execution);
this.iconPath = executionStatusIcons[execution.status];
this.label = this.getLabel(execution);
this.isAutoRefreshing = execution.status === "processing" || execution.status === "waiting";
ext.tree?.functions?.refreshChild(this);
await sleep(1000);
this.autoRefresh();
}
getLabel(execution: Execution): string {
if (execution.status === "completed" || execution.status === "failed") {
return `${this.getCreated(execution)} (${this.getExecutionTime(execution)}s)`;
return `${this.getCreated(execution)} (${execution.time.toPrecision(2)}s)`;
}
return `${this.getCreated(execution)} (${execution.status})`;
}
getExecutionTime(execution: Execution): string {
return execution.time.toPrecision(2);
}
getContextValue(execution: Execution): string {
if (execution.status === "completed" || execution.status === "failed") {
if (execution.stderr === "" && execution.stdout === "") {

View file

@ -1,47 +1,21 @@
import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
import { Execution, ExecutionList } from "../../../appwrite";
import { Execution, ExecutionList } from '../../../appwrite';
import { functionsClient } from "../../../client";
import { ExecutionTreeItem } from "./ExecutionTreeItem";
import { FunctionTreeItem } from "../FunctionTreeItem";
import { ext } from "../../../extensionVariables";
import { AppwriteTreeItemBase } from "../../../ui/AppwriteTreeItemBase";
import { AppwriteTreeItemBase } from '../../../ui/AppwriteTreeItemBase';
import { ExecutionTreeItem } from './ExecutionTreeItem';
import { FunctionTreeItem } from '../FunctionTreeItem';
export class ExecutionsTreeItem extends AppwriteTreeItemBase<FunctionTreeItem> {
constructor(public readonly parent: FunctionTreeItem) {
super(parent, "Executions");
}
private executionsToShow = 10;
public async getChildren(): Promise<TreeItem[]> {
if (!functionsClient) {
return [];
}
const executions: ExecutionList | undefined = await functionsClient.listExecutions(
this.parent.func.$id,
undefined,
this.executionsToShow,
undefined,
"DESC"
);
const children = executions?.executions.map((execution: Execution) => new ExecutionTreeItem(this, execution)) ?? [
new TreeItem("No executions."),
];
if (children.length === 0) {
children.push(new TreeItem("No executions."));
}
ext.outputChannel.appendLog(`Found ${executions?.sum} executions`);
if (executions?.sum ?? (0 > this.executionsToShow && this.executionsToShow !== 100)) {
const viewMoreItem: TreeItem = {
command: {
command: "vscode-appwrite.viewMore",
arguments: [this],
title: "View more",
},
label: "View more...",
};
children.push(viewMoreItem);
}
const executions: ExecutionList | undefined = await functionsClient.listExecutions(this.parent.func.$id, undefined, undefined, undefined, 'DESC');
const children = executions?.executions.map((execution: Execution) => new ExecutionTreeItem(this, execution)) ?? [new TreeItem('No exeuctions.')];
return children;
}
@ -50,12 +24,4 @@ export class ExecutionsTreeItem extends AppwriteTreeItemBase<FunctionTreeItem> {
contextValue = "executions";
iconPath = new ThemeIcon("history");
async viewMore(): Promise<void> {
this.executionsToShow += 10;
if (this.executionsToShow > 100) {
this.executionsToShow = 100;
}
ext.tree?.functions?.refreshChild(this);
}
}

View file

@ -3,7 +3,7 @@ import { Function } from "../../../appwrite";
import { functionsClient } from "../../../client";
import { appwriteSystemEvents } from "../../../constants";
import { ext } from "../../../extensionVariables";
import { EnumEditableTreeItemBase } from "../../common/editable/EnumEditableTreeItem";
import { EnumEditableTreeItemBase } from "../../common/EnumEditableTreeItem";
import { FunctionSettingsTreeItem } from "./FunctionSettingsTreeItem";
export class EventsTreeItem extends EnumEditableTreeItemBase {

View file

@ -1,7 +1,7 @@
import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
import { Function } from "../../../appwrite";
import { functionsClient } from "../../../client";
import { AppwriteTreeItemBase } from '../../../ui/AppwriteTreeItemBase';
import { AppwriteTreeItemBase } from "../../../ui/AppwriteTreeItemBase";
import { ChildTreeItem } from "../../ChildTreeItem";
import { FunctionTreeItem } from "../FunctionTreeItem";
import { EventsTreeItem } from "./EventsTreeItem";

View file

@ -2,7 +2,7 @@ import { InputBoxOptions, MarkdownString } from "vscode";
import { Function } from "../../../appwrite";
import { functionsClient } from "../../../client";
import { ext } from "../../../extensionVariables";
import { StringEditableTreeItemBase } from '../../common/editable/StringEditableTreeItem';
import { StringEditableTreeItemBase } from '../../common/StringEditableTreeItem';
import { FunctionSettingsTreeItem } from "./FunctionSettingsTreeItem";
const tooltip = "Function name";

View file

@ -5,7 +5,7 @@ import { ext } from "../../../extensionVariables";
import cron from "cron-validate";
import { FunctionSettingsTreeItem } from "./FunctionSettingsTreeItem";
import cronstrue from "cronstrue";
import { StringEditableTreeItemBase } from '../../common/editable/StringEditableTreeItem';
import { StringEditableTreeItemBase } from '../../common/StringEditableTreeItem';
export class ScheduleTreeItem extends StringEditableTreeItemBase {
private readonly func: Function;

View file

@ -2,7 +2,7 @@ import { InputBoxOptions, MarkdownString } from "vscode";
import { Function } from "../../../appwrite";
import { functionsClient } from "../../../client";
import { ext } from "../../../extensionVariables";
import { StringEditableTreeItemBase } from "../../common/editable/StringEditableTreeItem";
import { StringEditableTreeItemBase } from "../../common/StringEditableTreeItem";
function isNumeric(str: string) {
console.log("here");

View file

@ -2,7 +2,7 @@ import { InputBoxOptions, MarkdownString, window } from "vscode";
import { Function } from "../../../appwrite";
import { functionsClient } from "../../../client";
import { ext } from "../../../extensionVariables";
import { StringEditableTreeItemBase } from "../../common/editable/StringEditableTreeItem";
import { StringEditableTreeItemBase } from "../../common/StringEditableTreeItem";
import { VarsTreeItem } from "./VarsTreeItem";
const tooltip = "Environment var";

View file

@ -1,6 +1,6 @@
import { TreeItem, TreeItemCollapsibleState } from "vscode";
import { Vars } from "../../../appwrite";
import { AppwriteTreeItemBase } from '../../../ui/AppwriteTreeItemBase';
import { AppwriteTreeItemBase } from "../../../ui/AppwriteTreeItemBase";
import { FunctionSettingsTreeItem } from "./FunctionSettingsTreeItem";
import { VarTreeItem } from "./VarTreeItem";

View file

@ -10,7 +10,7 @@ export class TagTreeItem extends TreeItem {
const active = func.tag === tag.$id;
this.label = `${msToDate(tag.dateCreated)}${active ? ' (Active)' : ''}`;
this.description = tag.$id;
this.iconPath = new ThemeIcon(active ? 'circle-large-filled' : 'circle-large-outline');
this.iconPath = new ThemeIcon(active ? 'circle-filled' : 'circle-outline');
this.contextValue = `tag${active ? '_active' : ''}`;
this.tooltip = new MarkdownString(`ID: ${tag.$id} \nCreated: ${msToDate(tag.dateCreated)} \nCommand: ${tag.command} \nSize: ${tag.size}B`);
}

View file

@ -14,22 +14,7 @@ export class TagsTreeItem extends AppwriteTreeItemBase<FunctionTreeItem> {
return [];
}
const tags = await functionsClient.listTags(this.parent.func.$id);
const children = tags?.tags.sort((a, b) => b.dateCreated - a.dateCreated).map((tag) => new TagTreeItem(this, tag)) ?? [new TreeItem('No tags.')];
if (children.length === 0) {
const noTagsItem: TreeItem = {
command: {
command: "vscode-appwrite.CreateTag",
title: "Create tag",
arguments: [this],
tooltip: "Create a tag"
},
label: "Create a tag",
iconPath: new ThemeIcon("cloud-upload"),
};
children.push(noTagsItem);
}
return children;
return tags?.tags.sort((a, b) => b.dateCreated - a.dateCreated).map((tag) => new TagTreeItem(this, tag)) ?? [new TreeItem('No tags.')];
}
collapsibleState = TreeItemCollapsibleState.Collapsed;

View file

@ -7,7 +7,4 @@ export abstract class AppwriteTreeItemBase<Parent = void> extends TreeItem {
abstract getChildren?(): Promise<TreeItem[]>;
viewMore(): Promise<void> {
return Promise.resolve();
}
}

View file

@ -1,19 +1,42 @@
import { QuickPickItem, window } from "vscode";
import { Collection, CollectionsList } from "../appwrite";
import { client } from "../client";
import { AppwriteSDK } from "../constants";
import AppwriteCall from "../utils/AppwriteCall";
export type CreateRuleWizardContext = {
label: string;
key: string;
type: keyof typeof ruleTypes;
default: any;
required: boolean;
array: boolean;
list?: string[];
};
export async function createRuleWizard(): Promise<CreateRuleWizardContext | undefined> {
const label = await window.showInputBox({
placeHolder: "Label",
prompt: "Attribute internal display name",
});
if (label === undefined) {
return;
}
const key = await window.showInputBox({
placeHolder: "Key",
prompt: "Attribute key name. Used as the document JSON key in the Database API.",
});
if (key === undefined) {
return;
}
const ruleTypeItems: QuickPickItem[] = Object.entries(ruleTypes).map(([label, description]) => ({
label,
description,
}));
const type = await window.showQuickPick(ruleTypeItems);
if (type === undefined) {
return;
}
if (label && key && type) {
return { label, key, type: (type.label as unknown) as keyof typeof ruleTypes };
}
return undefined;
}
const ruleTypes = {
text: "Any string value.",
numeric: "Any integer or float value.",
@ -22,119 +45,6 @@ const ruleTypes = {
url: "Any valid URL.",
email: "Any valid email address.",
ip: "Any valid IP v4 or v6 address.",
document: "Accept a valid child document from specified collection(s).",
document:
"Accept a valid child document. When using this type you are also required to pass the 'list' parameter with an array of the collections UID values of the document types you want to accept.",
};
type RuleType = keyof typeof ruleTypes;
export async function createRuleWizard(collection: Collection): Promise<CreateRuleWizardContext | undefined> {
const label = await window.showInputBox({
placeHolder: "Attribute label",
prompt: "Attribute internal display name",
validateInput: (value) => {
if (value === "") {
return "Label cannot be empty.";
}
},
});
if (label === undefined) {
return;
}
const key = await window.showInputBox({
placeHolder: "Attribute key name",
prompt: "Attribute key name. Used as the document JSON key in the Database API.",
ignoreFocusOut: true,
validateInput: (value) => {
if (value === "") {
return "Key name cannot be empty.";
}
},
});
if (key === undefined) {
return;
}
const ruleTypeItems: QuickPickItem[] = Object.entries(ruleTypes).map(([label, description]) => ({
label,
detail: description,
}));
const typeItem = await window.showQuickPick(ruleTypeItems, { placeHolder: "Rule value type." });
const type: RuleType | undefined = (typeItem?.label as RuleType) ?? undefined;
if (typeItem === undefined || type === undefined) {
return;
}
let list: string[] | undefined = undefined;
if (type === "document") {
const databaseSdk = new AppwriteSDK.Database(client);
const collectionsList = await AppwriteCall<CollectionsList, CollectionsList>(databaseSdk.listCollections());
if (collectionsList === undefined) {
window.showErrorMessage("Could not get collections list.");
return;
}
if (collectionsList) {
const collections = collectionsList.collections.filter((c) => c.$id !== collection.$id);
const qpItems: QuickPickItem[] = collections.map((collection) => ({
label: collection.name,
description: collection.$id,
}));
const listInput = await window.showQuickPick(qpItems, {
canPickMany: true,
placeHolder: "Collections which contain valid child documents for this document attribute.",
ignoreFocusOut: true,
});
list = listInput?.map((item) => item.description as string) ?? [];
}
}
if (label === "document" && list === undefined) {
return;
}
const array = await window.showQuickPick(["Primitive", "Array"], {
placeHolder: "Decide if this rule is a primitive or an array of values.",
ignoreFocusOut: true,
});
if (array === undefined) {
return;
}
const required = await window.showQuickPick(["Required", "Optional"], {
placeHolder: "Decide if this rule value is required in order to pass document validation.",
ignoreFocusOut: true,
});
if (required === undefined) {
return;
}
const defaultValue = await window.showInputBox({
placeHolder: "Default value (press Enter to skip)",
prompt: "Default value for this rule type. Make sure that the default value is able to pass validation in order to avoid errors when skipping optional values.",
ignoreFocusOut: true,
});
if (defaultValue === undefined) {
return;
}
if (label && key && type) {
return {
label,
key,
type,
default: defaultValue,
array: array === "Array",
required: required === "Required",
list,
};
}
return undefined;
}

View file

@ -1,9 +1,5 @@
import dayjs = require("dayjs");
import utc = require("dayjs/plugin/utc");
import timezone = require("dayjs/plugin/timezone"); // dependent on utc plugin
dayjs.extend(utc);
dayjs.extend(timezone);
import dayjs = require('dayjs');
export function msToDate(ms: number): string {
return dayjs(ms * 1000).tz(dayjs.tz.guess()).format("LTS");
return dayjs(ms).format("LTS");
}

View file

@ -1,5 +0,0 @@
export function sleep(ms: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

View file

@ -2,8 +2,8 @@ import tar = require("tar");
import { Uri, window, workspace } from "vscode";
import { ext } from "../extensionVariables";
import * as path from "path";
import * as os from "os";
import * as fs from "fs";
import { sleep } from './sleep';
export async function getTarReadStream(folder: Uri): Promise<string | undefined> {
try {
@ -15,14 +15,11 @@ export async function getTarReadStream(folder: Uri): Promise<string | undefined>
window.showErrorMessage("No workspace open.");
return;
}
ext.outputChannel.appendLog(`Creating '${tarName}' in '${workspace.workspaceFolders?.[0].uri.fsPath}'...`);
const tarFilePath = path.join(ext.context?.globalStorageUri.fsPath ?? '', tarName);
await workspace.fs.createDirectory(ext.context.globalStorageUri);
tar.create({ gzip: true, cwd: cwd, mode: 1777 }, [path.relative(cwd, folder.fsPath)]).pipe(fs.createWriteStream(tarFilePath));
const tarFilePath = path.join(os.tmpdir(), tarName);
await sleep(500);
tar.create({ gzip: true, cwd: cwd }, [path.relative(cwd, folder.fsPath)]).pipe(fs.createWriteStream(tarFilePath));
ext.outputChannel.appendLog(`Created ${tarFilePath}`);

View file

@ -1,6 +0,0 @@
import { Progress } from 'vscode';
export type ProgressMessage = Progress<{
message?: string | undefined;
increment?: number | undefined;
}>;