Compare commits

..

4 commits

Author SHA1 Message Date
alexweininger
6e9d4e7f7b File upload/download without settings 2021-06-04 00:41:12 -07:00
alexweininger
57cb4626e4 Execute function after activating tag 2021-06-03 23:05:16 -07:00
alexweininger
1ed67e7c10 Open tag in browser after creation 2021-06-03 23:01:51 -07:00
alexweininger
095483ef9d Add "Open collection in browser" command 2021-06-03 22:51:02 -07:00
14 changed files with 5440 additions and 122 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

@ -6,10 +6,6 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
## [Unreleased] ## [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 ## [0.1.2] - 2021-6-03
## Added ## 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)! - 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)!

5347
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
"name": "vscode-appwrite", "name": "vscode-appwrite",
"displayName": "Appwrite", "displayName": "Appwrite",
"description": "Manage your Appwrite resources right from VS Code!", "description": "Manage your Appwrite resources right from VS Code!",
"version": "0.1.3", "version": "0.1.2",
"engines": { "engines": {
"vscode": "^1.55.0" "vscode": "^1.55.0"
}, },
@ -335,10 +335,28 @@
"icon": "$(link-external)", "icon": "$(link-external)",
"category": "Appwrite" "category": "Appwrite"
}, },
{
"command": "vscode-appwrite.openCollectionInBrowser",
"title": "Open collection in browser",
"icon": "$(link-external)",
"category": "Appwrite"
},
{ {
"command": "vscode-appwrite.viewMore", "command": "vscode-appwrite.viewMore",
"title": "View more", "title": "View more",
"category": "Appwrite" "category": "Appwrite"
},
{
"command": "vscode-appwrite.uploadFile",
"title": "Upload file to storage",
"icon": "$(cloud-upload)",
"category": "Appwrite"
},
{
"command": "vscode-appwrite.downloadFile",
"title": "Download file",
"icon": "$(cloud-download)",
"category": "Appwrite"
} }
], ],
"views": { "views": {
@ -450,6 +468,11 @@
"command": "vscode-appwrite.createFunction", "command": "vscode-appwrite.createFunction",
"when": "view == Functions", "when": "view == Functions",
"group": "navigation" "group": "navigation"
},
{
"command": "vscode-appwrite.uploadFile",
"when": "view == Storage",
"group": "navigation"
} }
], ],
"view/item/context": [ "view/item/context": [
@ -488,6 +511,11 @@
"command": "vscode-appwrite.viewCollectionAsJson", "command": "vscode-appwrite.viewCollectionAsJson",
"when": "viewItem == collection" "when": "viewItem == collection"
}, },
{
"command": "vscode-appwrite.openCollectionInBrowser",
"when": "viewItem == collection",
"group": "inline"
},
{ {
"command": "vscode-appwrite.deleteCollection", "command": "vscode-appwrite.deleteCollection",
"when": "viewItem == collection" "when": "viewItem == collection"
@ -620,6 +648,11 @@
"command": "vscode-appwrite.CreateTag", "command": "vscode-appwrite.CreateTag",
"when": "viewItem =~ /^tags$/", "when": "viewItem =~ /^tags$/",
"group": "inline" "group": "inline"
},
{
"command": "vscode-appwrite.downloadFile",
"when": "viewItem =~ /^file$/",
"group": "inline"
} }
], ],
"explorer/context": [ "explorer/context": [
@ -726,11 +759,6 @@
"type": "string", "type": "string",
"default": "", "default": "",
"markdownDescription": "Project id of the active project, see [docs](https://github.com/streamlux/vscode-appwrite/) for more information." "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"
} }
} }
} }
@ -769,6 +797,7 @@
"cron-validate": "^1.4.3", "cron-validate": "^1.4.3",
"cronstrue": "^1.113.0", "cronstrue": "^1.113.0",
"dayjs": "^1.10.4", "dayjs": "^1.10.4",
"downloads-folder": "^3.0.1",
"fs-extra": "^9.1.0", "fs-extra": "^9.1.0",
"node-appwrite": "^2.2.3", "node-appwrite": "^2.2.3",
"tar": "^6.1.0" "tar": "^6.1.0"

3
src/appwrite.d.ts vendored
View file

@ -362,6 +362,9 @@ export type StorageClient = {
createFile: (file: any, read?: string[], write?: string[]) => Promise<any>; createFile: (file: any, read?: string[], write?: string[]) => Promise<any>;
listFiles: () => Promise<any>; listFiles: () => Promise<any>;
getFile: (fileId: string) => Promise<any>; getFile: (fileId: string) => Promise<any>;
getFileDownload: (fileId: string) => Promise<any>;
getFileView: (fileId: string) => Promise<any>;
deleteFile: (fileId: string) => Promise<any>;
}; };
type Vars = Record<string, any>; type Vars = Record<string, any>;

View file

@ -14,6 +14,14 @@ export class Storage {
return await AppwriteCall(this.storage.listFiles()); return await AppwriteCall(this.storage.listFiles());
} }
public async getFileDownload(fileId: string): Promise<any> {
return await AppwriteCall(this.storage.getFileDownload(fileId));
}
public async getFileView(fileId: string): Promise<any> {
return await AppwriteCall(this.storage.getFileView(fileId));
}
public async createFile(file: ReadStream): Promise<void> { public async createFile(file: ReadStream): Promise<void> {
return await AppwriteCall(this.storage.createFile(file)); return await AppwriteCall(this.storage.createFile(file));
} }

View file

@ -0,0 +1,6 @@
import { CollectionTreeItem } from '../../tree/database/CollectionTreeItem';
import { openUrl } from '../../utils/openUrl';
export async function openCollectionInBrowser(treeItem: CollectionTreeItem): Promise<void> {
openUrl(treeItem.getUrl());
}

View file

@ -1,30 +1,8 @@
import { workspace } from "vscode";
import { DocumentTreeItem } from "../../tree/database/DocumentTreeItem"; import { DocumentTreeItem } from "../../tree/database/DocumentTreeItem";
import { openReadOnlyJson } from "../../ui/openReadonlyContent"; 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> { export async function viewDocumentAsJson(documentTreeItem: DocumentTreeItem): Promise<void> {
const document = documentTreeItem.document; const documentId = documentTreeItem.document["$id"];
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;
}
});
}
await openReadOnlyJson( await openReadOnlyJson(
{ {
label: documentId, label: documentId,

View file

@ -8,6 +8,9 @@ import { selectWorkspaceFolder } from "../../utils/workspace";
import { ProgressMessage } from "../../utils/types"; import { ProgressMessage } from "../../utils/types";
import { Tag } from "../../appwrite"; import { Tag } from "../../appwrite";
import { activateTag } from "./activateTag"; import { activateTag } from "./activateTag";
import { sleep } from '../../utils/sleep';
import { openFunctionTagsInBrowser } from './openFunctionTagsInBrowser';
import { executeFunction } from './createExecution';
export async function createTag(item?: TagsTreeItem | Uri): Promise<void> { export async function createTag(item?: TagsTreeItem | Uri): Promise<void> {
if (item instanceof Uri) { if (item instanceof Uri) {
@ -136,7 +139,8 @@ async function createTagFromUri(functionId: string, command: string, uri: Uri, p
return; return;
} }
// somehow makes the upload work // somehow makes the upload work
await workspace.fs.readFile(Uri.file(tarFilePath)); // await workspace.fs.readFile(Uri.file(tarFilePath));
await sleep(1000);
progress.report({ message: "Uploading tag", increment: 60 }); progress.report({ message: "Uploading tag", increment: 60 });
try { try {
return await functionsClient.createTag(functionId, command, fs.createReadStream(tarFilePath)); return await functionsClient.createTag(functionId, command, fs.createReadStream(tarFilePath));
@ -155,9 +159,17 @@ async function tagNotification(tag: Tag): Promise<void> {
); );
if (action === "Activate tag") { if (action === "Activate tag") {
await activateTag(tag); await activateTag(tag);
const action = await window.showInformationMessage(
`Successfully activated tag.`,
"Execute function",
);
if (action === 'Execute function') {
await executeFunction(tag.functionId);
}
} }
if (action === "View in console") { if (action === "View in console") {
// //
await openFunctionTagsInBrowser(tag.functionId);
} }
return; return;
} }

View file

@ -3,11 +3,13 @@ import { ExecutionsTreeItem } from '../../tree/functions/executions/ExecutionsTr
import { openUrl } from '../../utils/openUrl'; import { openUrl } from '../../utils/openUrl';
import { getConsoleUrlFromEndpoint } from '../users/openUserInConsole'; import { getConsoleUrlFromEndpoint } from '../users/openUserInConsole';
export async function openFunctionTagsInBrowser(treeItem: ExecutionsTreeItem): Promise<void> { export async function openFunctionTagsInBrowser(treeItem: ExecutionsTreeItem | string): Promise<void> {
const func = treeItem.parent.func;
const funcId = treeItem instanceof ExecutionsTreeItem ? treeItem.parent.func.$id : treeItem;
const consoleUrl = getConsoleUrlFromEndpoint(clientConfig.endpoint); const consoleUrl = getConsoleUrlFromEndpoint(clientConfig.endpoint);
// https://console.streamlux.com/console/functions/function?id=60b1836a8e5d9&project=605ce39a30c01 // https://console.streamlux.com/console/functions/function?id=60b1836a8e5d9&project=605ce39a30c01
const url = `${consoleUrl}/functions/function?id=${func.$id}&project=${clientConfig.projectId}`; const url = `${consoleUrl}/functions/function?id=${funcId}&project=${clientConfig.projectId}`;
openUrl(url); openUrl(url);
} }

View file

@ -43,6 +43,9 @@ import { openFunctionSettingsInBrowser } from './functions/openFunctionSettingsI
import { openFunctionTagsInBrowser } from './functions/openFunctionTagsInBrowser'; import { openFunctionTagsInBrowser } from './functions/openFunctionTagsInBrowser';
import { viewMore } from './common/viewMore'; import { viewMore } from './common/viewMore';
import { openCollectionInBrowser } from './database/openCollectionInBrowser';
import { uploadFile } from './storage/uploadFile';
import { downloadFile } from './storage/downloadFile';
class CommandRegistrar { class CommandRegistrar {
constructor(private readonly context: ExtensionContext) {} constructor(private readonly context: ExtensionContext) {}
@ -106,6 +109,7 @@ export function registerCommands(context: ExtensionContext): void {
registerCommand("createPermission", createPermission, "database"); registerCommand("createPermission", createPermission, "database");
registerCommand("deletePermission", deletePermission, "database"); registerCommand("deletePermission", deletePermission, "database");
registerCommand("editPermission", editPermission, "database"); registerCommand("editPermission", editPermission, "database");
registerCommand("openCollectionInBrowser", openCollectionInBrowser);
/** Health **/ /** Health **/
registerCommand("refreshHealth", undefined, "health"); registerCommand("refreshHealth", undefined, "health");
@ -113,6 +117,9 @@ export function registerCommands(context: ExtensionContext): void {
/** Storage **/ /** Storage **/
registerCommand("refreshStorage", undefined, "storage"); registerCommand("refreshStorage", undefined, "storage");
registerCommand("uploadFile", uploadFile, "storage");
registerCommand("downloadFile", downloadFile);
registerCommand("openStorageDocumentation", () => openDocumentation("storage")); registerCommand("openStorageDocumentation", () => openDocumentation("storage"));
/** Projects **/ /** Projects **/

View file

@ -0,0 +1,29 @@
import { ProgressLocation, Uri, window, workspace } from "vscode";
import { storageClient } from "../../client";
import * as fs from "fs";
import { FileTreeItem } from "../../tree/storage/FileTreeItem";
import downloadsFolder = require("downloads-folder");
import { File } from "../../appwrite";
import { ProgressMessage } from "../../utils/types";
import { CancellationToken } from "vscode";
export async function downloadFile(item: FileTreeItem | File): Promise<void> {
const file = item instanceof FileTreeItem ? item.file : item;
const data = await window.withProgress(
{ location: ProgressLocation.Notification, title: `Downloading ${file.name}`, cancellable: false },
async (progress: ProgressMessage, _token: CancellationToken): Promise<Buffer> => {
const data = await storageClient?.getFileDownload(file.$id);
progress.report({ message: "Download finished" });
return data;
}
);
const defaultUriBase = workspace.workspaceFolders?.[0].uri ?? Uri.parse(downloadsFolder());
const defaultUri = Uri.joinPath(defaultUriBase, file.name);
const destination = await window.showSaveDialog({ saveLabel: "Save", title: file.name, defaultUri });
if (data && destination) {
await fs.promises.writeFile(destination.fsPath, data);
}
}

View file

@ -0,0 +1,14 @@
import { window } from "vscode";
import { storageClient } from "../../client";
import * as fs from "fs";
export async function uploadFile(): Promise<void> {
try {
const file = await window.showOpenDialog({ canSelectFiles: true, canSelectFolders: false, canSelectMany: false });
if (file) {
await storageClient?.createFile(fs.createReadStream(file[0].fsPath));
}
} catch (e) {
window.showErrorMessage("Failed to upload file.");
}
}

View file

@ -1,6 +1,7 @@
import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
import { Collection } from "../../appwrite"; import { Collection } from "../../appwrite";
import { databaseClient } from "../../client"; import { clientConfig, databaseClient } from "../../client";
import { getConsoleUrlFromEndpoint } from '../../commands/users/openUserInConsole';
import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase"; import { AppwriteTreeItemBase } from "../../ui/AppwriteTreeItemBase";
import { DatabaseTreeItemProvider } from "./DatabaseTreeItemProvider"; import { DatabaseTreeItemProvider } from "./DatabaseTreeItemProvider";
import { DocumentsTreeItem } from "./DocumentsTreeItem"; import { DocumentsTreeItem } from "./DocumentsTreeItem";
@ -12,6 +13,12 @@ export class CollectionTreeItem extends AppwriteTreeItemBase {
super(undefined, collection.name); super(undefined, collection.name);
} }
// https://console.streamlux.com/console/database/collection?id=607cb2d6a21a8&project=605ce39a30c01
public getUrl(): string {
const consoleUrl = getConsoleUrlFromEndpoint(clientConfig.endpoint);
return `${consoleUrl}/database/collection?id=${this.collection.$id}&project=${clientConfig.projectId}`;
}
public async getChildren(): Promise<TreeItem[]> { public async getChildren(): Promise<TreeItem[]> {
return [new RulesTreeItem(this), new PermissionsTreeItem(this), new DocumentsTreeItem(this)]; return [new RulesTreeItem(this), new PermissionsTreeItem(this), new DocumentsTreeItem(this)];
} }